Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2009 Younes Manton.
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28. #include <assert.h>
  29.  
  30. #include <X11/Xlibint.h>
  31. #include <X11/extensions/XvMClib.h>
  32.  
  33. #include "pipe/p_screen.h"
  34. #include "pipe/p_video_decoder.h"
  35. #include "pipe/p_video_state.h"
  36. #include "pipe/p_state.h"
  37.  
  38. #include "util/u_memory.h"
  39.  
  40. #include "vl/vl_csc.h"
  41. #include "vl/vl_winsys.h"
  42.  
  43. #include "xvmc_private.h"
  44.  
  45. static Status Validate(Display *dpy, XvPortID port, int surface_type_id,
  46.                        unsigned int width, unsigned int height, int flags,
  47.                        bool *found_port, int *screen, int *chroma_format,
  48.                        int *mc_type, int *surface_flags,
  49.                        unsigned short *subpic_max_w,
  50.                        unsigned short *subpic_max_h)
  51. {
  52.    bool found_surface = false;
  53.    XvAdaptorInfo *adaptor_info;
  54.    unsigned int num_adaptors;
  55.    int num_types;
  56.    unsigned int max_width = 0, max_height = 0;
  57.    Status ret;
  58.  
  59.    assert(dpy);
  60.    assert(found_port);
  61.    assert(screen);
  62.    assert(chroma_format);
  63.    assert(mc_type);
  64.    assert(surface_flags);
  65.    assert(subpic_max_w);
  66.    assert(subpic_max_h);
  67.  
  68.    *found_port = false;
  69.  
  70.    for (unsigned int i = 0; i < XScreenCount(dpy); ++i) {
  71.       ret = XvQueryAdaptors(dpy, XRootWindow(dpy, i), &num_adaptors, &adaptor_info);
  72.       if (ret != Success)
  73.          return ret;
  74.  
  75.       for (unsigned int j = 0; j < num_adaptors && !*found_port; ++j) {
  76.          for (unsigned int k = 0; k < adaptor_info[j].num_ports && !*found_port; ++k) {
  77.             XvMCSurfaceInfo *surface_info;
  78.  
  79.             if (adaptor_info[j].base_id + k != port)
  80.                continue;
  81.  
  82.             *found_port = true;
  83.  
  84.             surface_info = XvMCListSurfaceTypes(dpy, adaptor_info[j].base_id, &num_types);
  85.             if (!surface_info) {
  86.                XvFreeAdaptorInfo(adaptor_info);
  87.                return BadAlloc;
  88.             }
  89.  
  90.             for (unsigned int l = 0; l < num_types && !found_surface; ++l) {
  91.                if (surface_info[l].surface_type_id != surface_type_id)
  92.                   continue;
  93.  
  94.                found_surface = true;
  95.                max_width = surface_info[l].max_width;
  96.                max_height = surface_info[l].max_height;
  97.                *chroma_format = surface_info[l].chroma_format;
  98.                *mc_type = surface_info[l].mc_type;
  99.                *surface_flags = surface_info[l].flags;
  100.                *subpic_max_w = surface_info[l].subpicture_max_width;
  101.                *subpic_max_h = surface_info[l].subpicture_max_height;
  102.                *screen = i;
  103.  
  104.                XVMC_MSG(XVMC_TRACE, "[XvMC] Found requested context surface format.\n" \
  105.                                     "[XvMC]   screen=%u, port=%u\n" \
  106.                                     "[XvMC]   id=0x%08X\n" \
  107.                                     "[XvMC]   max width=%u, max height=%u\n" \
  108.                                     "[XvMC]   chroma format=0x%08X\n" \
  109.                                     "[XvMC]   acceleration level=0x%08X\n" \
  110.                                     "[XvMC]   flags=0x%08X\n" \
  111.                                     "[XvMC]   subpicture max width=%u, max height=%u\n",
  112.                                     i, port, surface_type_id, max_width, max_height, *chroma_format,
  113.                                     *mc_type, *surface_flags, *subpic_max_w, *subpic_max_h);
  114.             }
  115.  
  116.             free(surface_info);
  117.          }
  118.       }
  119.  
  120.       XvFreeAdaptorInfo(adaptor_info);
  121.    }
  122.  
  123.    if (!*found_port) {
  124.       XVMC_MSG(XVMC_ERR, "[XvMC] Could not find a suitable port.\n");
  125.       return XvBadPort;
  126.    }
  127.    if (!found_surface) {
  128.       XVMC_MSG(XVMC_ERR, "[XvMC] Could not find a suitable surface.\n");
  129.       return BadMatch;
  130.    }
  131.    if (width > max_width || height > max_height) {
  132.       XVMC_MSG(XVMC_ERR, "[XvMC] Requested context dimensions (w=%u,h=%u) too large (max w=%u,h=%u).\n",
  133.                width, height, max_width, max_height);
  134.       return BadValue;
  135.    }
  136.    if (flags != XVMC_DIRECT && flags != 0) {
  137.       XVMC_MSG(XVMC_ERR, "[XvMC] Invalid context flags 0x%08X.\n", flags);
  138.       return BadValue;
  139.    }
  140.  
  141.    return Success;
  142. }
  143.  
  144. static enum pipe_video_profile ProfileToPipe(int xvmc_profile)
  145. {
  146.    if (xvmc_profile & XVMC_MPEG_1)
  147.       assert(0);
  148.    if (xvmc_profile & XVMC_MPEG_2)
  149.       return PIPE_VIDEO_PROFILE_MPEG2_MAIN;
  150.    if (xvmc_profile & XVMC_H263)
  151.       assert(0);
  152.    if (xvmc_profile & XVMC_MPEG_4)
  153.       assert(0);
  154.  
  155.    assert(0);
  156.  
  157.    XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized profile 0x%08X.\n", xvmc_profile);
  158.  
  159.    return -1;
  160. }
  161.  
  162. static enum pipe_video_chroma_format FormatToPipe(int xvmc_format)
  163. {
  164.    switch (xvmc_format) {
  165.       case XVMC_CHROMA_FORMAT_420:
  166.          return PIPE_VIDEO_CHROMA_FORMAT_420;
  167.       case XVMC_CHROMA_FORMAT_422:
  168.          return PIPE_VIDEO_CHROMA_FORMAT_422;
  169.       case XVMC_CHROMA_FORMAT_444:
  170.          return PIPE_VIDEO_CHROMA_FORMAT_444;
  171.       default:
  172.          assert(0);
  173.    }
  174.  
  175.    XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized format 0x%08X.\n", xvmc_format);
  176.  
  177.    return -1;
  178. }
  179.  
  180. PUBLIC
  181. Status XvMCCreateContext(Display *dpy, XvPortID port, int surface_type_id,
  182.                          int width, int height, int flags, XvMCContext *context)
  183. {
  184.    bool found_port;
  185.    int scrn = 0;
  186.    int chroma_format = 0;
  187.    int mc_type = 0;
  188.    int surface_flags = 0;
  189.    unsigned short subpic_max_w = 0;
  190.    unsigned short subpic_max_h = 0;
  191.    Status ret;
  192.    struct vl_screen *vscreen;
  193.    struct pipe_context *pipe;
  194.    XvMCContextPrivate *context_priv;
  195.    vl_csc_matrix csc;
  196.  
  197.    XVMC_MSG(XVMC_TRACE, "[XvMC] Creating context %p.\n", context);
  198.  
  199.    assert(dpy);
  200.  
  201.    if (!context)
  202.       return XvMCBadContext;
  203.  
  204.    ret = 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);
  207.  
  208.    /* Success and XvBadPort have the same value */
  209.    if (ret != Success || !found_port)
  210.       return ret;
  211.  
  212.    /* XXX: Current limits */
  213.    if (chroma_format != XVMC_CHROMA_FORMAT_420) {
  214.       XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Unsupported chroma format.\n");
  215.       return BadImplementation;
  216.    }
  217.    if ((mc_type & ~XVMC_IDCT) != (XVMC_MOCOMP | XVMC_MPEG_2)) {
  218.       XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Non-MPEG2/Mocomp/iDCT acceleration unsupported.\n");
  219.       return BadImplementation;
  220.    }
  221.    if (surface_flags & XVMC_INTRA_UNSIGNED) {
  222.       XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Unsigned intra unsupported.\n");
  223.       return BadImplementation;
  224.    }
  225.  
  226.    context_priv = CALLOC(1, sizeof(XvMCContextPrivate));
  227.    if (!context_priv)
  228.       return BadAlloc;
  229.  
  230.    /* TODO: Reuse screen if process creates another context */
  231.    vscreen = vl_screen_create(dpy, scrn);
  232.  
  233.    if (!vscreen) {
  234.       XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL screen.\n");
  235.       FREE(context_priv);
  236.       return BadAlloc;
  237.    }
  238.  
  239.    pipe = vscreen->pscreen->context_create(vscreen->pscreen, vscreen);
  240.    if (!pipe) {
  241.       XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL context.\n");
  242.       vl_screen_destroy(vscreen);
  243.       FREE(context_priv);
  244.       return BadAlloc;
  245.    }
  246.  
  247.    context_priv->decoder = pipe->create_video_decoder
  248.    (
  249.       pipe, ProfileToPipe(mc_type),
  250.       (mc_type & XVMC_IDCT) ? PIPE_VIDEO_ENTRYPOINT_IDCT : PIPE_VIDEO_ENTRYPOINT_MC,
  251.       FormatToPipe(chroma_format),
  252.       width, height, 2,
  253.       true
  254.    );
  255.  
  256.    if (!context_priv->decoder) {
  257.       XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL decoder.\n");
  258.       pipe->destroy(pipe);
  259.       vl_screen_destroy(vscreen);
  260.       FREE(context_priv);
  261.       return BadAlloc;
  262.    }
  263.  
  264.    if (!vl_compositor_init(&context_priv->compositor, pipe)) {
  265.       XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL compositor.\n");
  266.       context_priv->decoder->destroy(context_priv->decoder);
  267.       pipe->destroy(pipe);
  268.       vl_screen_destroy(vscreen);
  269.       FREE(context_priv);
  270.       return BadAlloc;
  271.    }
  272.  
  273.    if (!vl_compositor_init_state(&context_priv->cstate, pipe)) {
  274.       XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL compositor state.\n");
  275.       vl_compositor_cleanup(&context_priv->compositor);
  276.       context_priv->decoder->destroy(context_priv->decoder);
  277.       pipe->destroy(pipe);
  278.       vl_screen_destroy(vscreen);
  279.       FREE(context_priv);
  280.       return BadAlloc;
  281.    }
  282.  
  283.  
  284.    context_priv->color_standard =
  285.       debug_get_bool_option("G3DVL_NO_CSC", FALSE) ?
  286.       VL_CSC_COLOR_STANDARD_IDENTITY : VL_CSC_COLOR_STANDARD_BT_601;
  287.    context_priv->procamp = vl_default_procamp;
  288.  
  289.    vl_csc_get_matrix
  290.    (
  291.       context_priv->color_standard,
  292.       &context_priv->procamp, true, &csc
  293.    );
  294.    vl_compositor_set_csc_matrix(&context_priv->cstate, (const vl_csc_matrix *)&csc);
  295.  
  296.    context_priv->vscreen = vscreen;
  297.    context_priv->pipe = pipe;
  298.    context_priv->subpicture_max_width = subpic_max_w;
  299.    context_priv->subpicture_max_height = subpic_max_h;
  300.  
  301.    context->context_id = XAllocID(dpy);
  302.    context->surface_type_id = surface_type_id;
  303.    context->width = width;
  304.    context->height = height;
  305.    context->flags = flags;
  306.    context->port = port;
  307.    context->privData = context_priv;
  308.  
  309.    SyncHandle();
  310.  
  311.    XVMC_MSG(XVMC_TRACE, "[XvMC] Context %p created.\n", context);
  312.  
  313.    return Success;
  314. }
  315.  
  316. PUBLIC
  317. Status XvMCDestroyContext(Display *dpy, XvMCContext *context)
  318. {
  319.    XvMCContextPrivate *context_priv;
  320.  
  321.    XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying context %p.\n", context);
  322.  
  323.    assert(dpy);
  324.  
  325.    if (!context || !context->privData)
  326.       return XvMCBadContext;
  327.  
  328.    context_priv = context->privData;
  329.    context_priv->decoder->destroy(context_priv->decoder);
  330.    vl_compositor_cleanup_state(&context_priv->cstate);
  331.    vl_compositor_cleanup(&context_priv->compositor);
  332.    context_priv->pipe->destroy(context_priv->pipe);
  333.    vl_screen_destroy(context_priv->vscreen);
  334.    FREE(context_priv);
  335.    context->privData = NULL;
  336.  
  337.    XVMC_MSG(XVMC_TRACE, "[XvMC] Context %p destroyed.\n", context);
  338.  
  339.    return Success;
  340. }
  341.