Subversion Repositories Kolibri OS

Rev

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

  1. #include "xorg_tracker.h"
  2.  
  3. #include <xf86xv.h>
  4. #include <X11/extensions/Xv.h>
  5. #include <fourcc.h>
  6.  
  7. #include "xorg_exa.h"
  8. #include "xorg_renderer.h"
  9. #include "xorg_exa_tgsi.h"
  10.  
  11. #include "cso_cache/cso_context.h"
  12. #include "util/u_sampler.h"
  13.  
  14. #include "pipe/p_screen.h"
  15.  
  16. /*XXX get these from pipe's texture limits */
  17. #define IMAGE_MAX_WIDTH         2048
  18. #define IMAGE_MAX_HEIGHT        2048
  19.  
  20. #define RES_720P_X 1280
  21. #define RES_720P_Y 720
  22.  
  23.  
  24. /* The ITU-R BT.601 conversion matrix for SDTV. */
  25. /* original, matrix, but we transpose it to
  26.  * make the shader easier
  27. static const float bt_601[] = {
  28.     1.0, 0.0, 1.4075,   ,
  29.     1.0, -0.3455, -0.7169, 0,
  30.     1.0, 1.7790, 0., 0,
  31. };*/
  32. static const float bt_601[] = {
  33.     1.0, 1.0, 1.0,        0.5,
  34.     0.0, -0.3455, 1.7790, 0,
  35.     1.4075, -0.7169, 0.,  0,
  36. };
  37.  
  38. /* The ITU-R BT.709 conversion matrix for HDTV. */
  39. /* original, but we transpose to make the conversion
  40.  * in the shader easier
  41. static const float bt_709[] = {
  42.     1.0, 0.0, 1.581, 0,
  43.     1.0, -0.1881, -0.47, 0,
  44.     1.0, 1.8629, 0., 0,
  45. };*/
  46. static const float bt_709[] = {
  47.     1.0,   1.0,     1.0,     0.5,
  48.     0.0,  -0.1881,  1.8629,  0,
  49.     1.581,-0.47   , 0.0,     0,
  50. };
  51.  
  52. #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
  53.  
  54. static Atom xvBrightness, xvContrast;
  55.  
  56. #define NUM_TEXTURED_ATTRIBUTES 2
  57. static XF86AttributeRec TexturedAttributes[NUM_TEXTURED_ATTRIBUTES] = {
  58.    {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
  59.    {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}
  60. };
  61.  
  62. #define NUM_FORMATS 3
  63. static XF86VideoFormatRec Formats[NUM_FORMATS] = {
  64.    {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
  65. };
  66.  
  67. static XF86VideoEncodingRec DummyEncoding[1] = {
  68.    {
  69.       0,
  70.       "XV_IMAGE",
  71.       IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
  72.       {1, 1}
  73.    }
  74. };
  75.  
  76. #define NUM_IMAGES 3
  77. static XF86ImageRec Images[NUM_IMAGES] = {
  78.    XVIMAGE_UYVY,
  79.    XVIMAGE_YUY2,
  80.    XVIMAGE_YV12,
  81. };
  82.  
  83. struct xorg_xv_port_priv {
  84.    struct xorg_renderer *r;
  85.  
  86.    RegionRec clip;
  87.  
  88.    int brightness;
  89.    int contrast;
  90.  
  91.    int current_set;
  92.    /* juggle two sets of seperate Y, U and V
  93.     * textures */
  94.    struct pipe_resource *yuv[2][3];
  95.    struct pipe_sampler_view *yuv_views[2][3];
  96. };
  97.  
  98.  
  99. static void
  100. stop_video(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
  101. {
  102.    struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data;
  103.  
  104.    REGION_EMPTY(pScrn->pScreen, &priv->clip);
  105. }
  106.  
  107. static int
  108. set_port_attribute(ScrnInfoPtr pScrn,
  109.                    Atom attribute, INT32 value, pointer data)
  110. {
  111.    struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data;
  112.  
  113.    if (attribute == xvBrightness) {
  114.       if ((value < -128) || (value > 127))
  115.          return BadValue;
  116.       priv->brightness = value;
  117.    } else if (attribute == xvContrast) {
  118.       if ((value < 0) || (value > 255))
  119.          return BadValue;
  120.       priv->contrast = value;
  121.    } else
  122.       return BadMatch;
  123.  
  124.    return Success;
  125. }
  126.  
  127. static int
  128. get_port_attribute(ScrnInfoPtr pScrn,
  129.                    Atom attribute, INT32 * value, pointer data)
  130. {
  131.    struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data;
  132.  
  133.    if (attribute == xvBrightness)
  134.       *value = priv->brightness;
  135.    else if (attribute == xvContrast)
  136.       *value = priv->contrast;
  137.    else
  138.       return BadMatch;
  139.  
  140.    return Success;
  141. }
  142.  
  143. static void
  144. query_best_size(ScrnInfoPtr pScrn,
  145.                 Bool motion,
  146.                 short vid_w, short vid_h,
  147.                 short drw_w, short drw_h,
  148.                 unsigned int *p_w, unsigned int *p_h, pointer data)
  149. {
  150.    if (vid_w > (drw_w << 1))
  151.       drw_w = vid_w >> 1;
  152.    if (vid_h > (drw_h << 1))
  153.       drw_h = vid_h >> 1;
  154.  
  155.    *p_w = drw_w;
  156.    *p_h = drw_h;
  157. }
  158.  
  159. static INLINE struct pipe_resource *
  160. create_component_texture(struct pipe_context *pipe,
  161.                          int width, int height)
  162. {
  163.    struct pipe_screen *screen = pipe->screen;
  164.    struct pipe_resource *tex = 0;
  165.    struct pipe_resource templ;
  166.  
  167.    memset(&templ, 0, sizeof(templ));
  168.    templ.target = PIPE_TEXTURE_2D;
  169.    templ.format = PIPE_FORMAT_L8_UNORM;
  170.    templ.last_level = 0;
  171.    templ.width0 = width;
  172.    templ.height0 = height;
  173.    templ.depth0 = 1;
  174.    templ.array_size = 1;
  175.    templ.bind = PIPE_BIND_SAMPLER_VIEW;
  176.  
  177.    tex = screen->resource_create(screen, &templ);
  178.  
  179.    return tex;
  180. }
  181.  
  182. static int
  183. check_yuv_textures(struct xorg_xv_port_priv *priv,  int width, int height)
  184. {
  185.    struct pipe_resource **dst = priv->yuv[priv->current_set];
  186.    struct pipe_sampler_view **dst_view = priv->yuv_views[priv->current_set];
  187.    struct pipe_sampler_view view_templ;
  188.    struct pipe_context *pipe = priv->r->pipe;
  189.  
  190.    if (!dst[0] ||
  191.        dst[0]->width0 != width ||
  192.        dst[0]->height0 != height) {
  193.       pipe_resource_reference(&dst[0], NULL);
  194.       pipe_sampler_view_reference(&dst_view[0], NULL);
  195.    }
  196.    if (!dst[1] ||
  197.        dst[1]->width0 != width ||
  198.        dst[1]->height0 != height) {
  199.       pipe_resource_reference(&dst[1], NULL);
  200.       pipe_sampler_view_reference(&dst_view[1], NULL);
  201.    }
  202.    if (!dst[2] ||
  203.        dst[2]->width0 != width ||
  204.        dst[2]->height0 != height) {
  205.       pipe_resource_reference(&dst[2], NULL);
  206.       pipe_sampler_view_reference(&dst_view[2], NULL);
  207.    }
  208.  
  209.    if (!dst[0]) {
  210.       dst[0] = create_component_texture(priv->r->pipe, width, height);
  211.       if (dst[0]) {
  212.          u_sampler_view_default_template(&view_templ,
  213.                                          dst[0],
  214.                                          dst[0]->format);
  215.          dst_view[0] = pipe->create_sampler_view(pipe, dst[0], &view_templ);
  216.       }
  217.    }
  218.  
  219.    if (!dst[1]) {
  220.       dst[1] = create_component_texture(priv->r->pipe, width, height);
  221.       if (dst[1]) {
  222.          u_sampler_view_default_template(&view_templ,
  223.                                          dst[1],
  224.                                          dst[1]->format);
  225.          dst_view[1] = pipe->create_sampler_view(pipe, dst[1], &view_templ);
  226.       }
  227.    }
  228.  
  229.    if (!dst[2]) {
  230.       dst[2] = create_component_texture(priv->r->pipe, width, height);
  231.       if (dst[2]) {
  232.          u_sampler_view_default_template(&view_templ,
  233.                                       dst[2],
  234.                                       dst[2]->format);
  235.          dst_view[2] = pipe->create_sampler_view(pipe, dst[2], &view_templ);
  236.       }
  237.    }
  238.  
  239.    if (!dst[0] || !dst[1] || !dst[2] || !dst_view[0] || !dst_view[1] || !dst_view[2] )
  240.       return BadAlloc;
  241.  
  242.    return Success;
  243. }
  244.  
  245. static int
  246. query_image_attributes(ScrnInfoPtr pScrn,
  247.                        int id,
  248.                        unsigned short *w, unsigned short *h,
  249.                        int *pitches, int *offsets)
  250. {
  251.    int size, tmp;
  252.  
  253.    if (*w > IMAGE_MAX_WIDTH)
  254.       *w = IMAGE_MAX_WIDTH;
  255.    if (*h > IMAGE_MAX_HEIGHT)
  256.       *h = IMAGE_MAX_HEIGHT;
  257.  
  258.    *w = (*w + 1) & ~1;
  259.    if (offsets)
  260.       offsets[0] = 0;
  261.  
  262.    switch (id) {
  263.    case FOURCC_YV12:
  264.       *h = (*h + 1) & ~1;
  265.       size = (*w + 3) & ~3;
  266.       if (pitches) {
  267.          pitches[0] = size;
  268.       }
  269.       size *= *h;
  270.       if (offsets) {
  271.          offsets[1] = size;
  272.       }
  273.       tmp = ((*w >> 1) + 3) & ~3;
  274.       if (pitches) {
  275.          pitches[1] = pitches[2] = tmp;
  276.       }
  277.       tmp *= (*h >> 1);
  278.       size += tmp;
  279.       if (offsets) {
  280.          offsets[2] = size;
  281.       }
  282.       size += tmp;
  283.       break;
  284.    case FOURCC_UYVY:
  285.    case FOURCC_YUY2:
  286.    default:
  287.       size = *w << 1;
  288.       if (pitches)
  289.          pitches[0] = size;
  290.       size *= *h;
  291.       break;
  292.    }
  293.  
  294.    return size;
  295. }
  296.  
  297. static void
  298. copy_packed_data(ScrnInfoPtr pScrn,
  299.                  struct xorg_xv_port_priv *port,
  300.                  int id,
  301.                  unsigned char *buf,
  302.                  int left,
  303.                  int top,
  304.                  unsigned short w, unsigned short h)
  305. {
  306.    int i, j;
  307.    struct pipe_resource **dst = port->yuv[port->current_set];
  308.    struct pipe_transfer *ytrans, *utrans, *vtrans;
  309.    struct pipe_context *pipe = port->r->pipe;
  310.    char *ymap, *vmap, *umap;
  311.    unsigned char y1, y2, u, v;
  312.    int yidx, uidx, vidx;
  313.    int y_array_size = w * h;
  314.  
  315.    ymap = pipe_transfer_map(pipe, dst[0],
  316.                             0, 0,
  317.                             PIPE_TRANSFER_WRITE,
  318.                             left, top, w, h, &ytrans);
  319.    umap = pipe_transfer_map(pipe, dst[1],
  320.                             0, 0,
  321.                             PIPE_TRANSFER_WRITE,
  322.                             left, top, w, h, &utrans);
  323.    vmap = pipe_transfer_map(pipe, dst[2],
  324.                             0, 0,
  325.                             PIPE_TRANSFER_WRITE,
  326.                             left, top, w, h, &vtrans);
  327.  
  328.    yidx = uidx = vidx = 0;
  329.  
  330.    switch (id) {
  331.    case FOURCC_YV12: {
  332.       int pitches[3], offsets[3];
  333.       unsigned char *y, *u, *v;
  334.       query_image_attributes(pScrn, FOURCC_YV12,
  335.                              &w, &h, pitches, offsets);
  336.  
  337.       y = buf + offsets[0];
  338.       v = buf + offsets[1];
  339.       u = buf + offsets[2];
  340.       for (i = 0; i < h; ++i) {
  341.          for (j = 0; j < w; ++j) {
  342.             int yoffset = (w*i+j);
  343.             int ii = (i|1), jj = (j|1);
  344.             int vuoffset = (w/2)*(ii/2) + (jj/2);
  345.             ymap[yidx++] = y[yoffset];
  346.             umap[uidx++] = u[vuoffset];
  347.             vmap[vidx++] = v[vuoffset];
  348.          }
  349.       }
  350.    }
  351.       break;
  352.    case FOURCC_UYVY:
  353.       for (i = 0; i < y_array_size; i +=2 ) {
  354.          /* extracting two pixels */
  355.          u  = buf[0];
  356.          y1 = buf[1];
  357.          v  = buf[2];
  358.          y2 = buf[3];
  359.          buf += 4;
  360.  
  361.          ymap[yidx++] = y1;
  362.          ymap[yidx++] = y2;
  363.          umap[uidx++] = u;
  364.          umap[uidx++] = u;
  365.          vmap[vidx++] = v;
  366.          vmap[vidx++] = v;
  367.       }
  368.       break;
  369.    case FOURCC_YUY2:
  370.       for (i = 0; i < y_array_size; i +=2 ) {
  371.          /* extracting two pixels */
  372.          y1 = buf[0];
  373.          u  = buf[1];
  374.          y2 = buf[2];
  375.          v  = buf[3];
  376.  
  377.          buf += 4;
  378.  
  379.          ymap[yidx++] = y1;
  380.          ymap[yidx++] = y2;
  381.          umap[uidx++] = u;
  382.          umap[uidx++] = u;
  383.          vmap[vidx++] = v;
  384.          vmap[vidx++] = v;
  385.       }
  386.       break;
  387.    default:
  388.       debug_assert(!"Unsupported yuv format!");
  389.       break;
  390.    }
  391.  
  392.    pipe->transfer_unmap(pipe, ytrans);
  393.    pipe->transfer_unmap(pipe, utrans);
  394.    pipe->transfer_unmap(pipe, vtrans);
  395. }
  396.  
  397.  
  398. static void
  399. setup_fs_video_constants(struct xorg_renderer *r, boolean hdtv)
  400. {
  401.    const int param_bytes = 12 * sizeof(float);
  402.    const float *video_constants = (hdtv) ? bt_709 : bt_601;
  403.  
  404.    renderer_set_constants(r, PIPE_SHADER_FRAGMENT,
  405.                           video_constants, param_bytes);
  406. }
  407.  
  408. static void
  409. draw_yuv(struct xorg_xv_port_priv *port,
  410.          float src_x, float src_y, float src_w, float src_h,
  411.          int dst_x, int dst_y, int dst_w, int dst_h)
  412. {
  413.    struct pipe_resource **textures = port->yuv[port->current_set];
  414.  
  415.    /*debug_printf("  draw_yuv([%d, %d, %d ,%d], [%d, %d, %d, %d])\n",
  416.                 src_x, src_y, src_w, src_h,
  417.                 dst_x, dst_y, dst_w, dst_h);*/
  418.    renderer_draw_yuv(port->r,
  419.                      src_x, src_y, src_w, src_h,
  420.                      dst_x, dst_y, dst_w, dst_h,
  421.                      textures);
  422. }
  423.  
  424. static void
  425. bind_blend_state(struct xorg_xv_port_priv *port)
  426. {
  427.    struct pipe_blend_state blend;
  428.  
  429.    memset(&blend, 0, sizeof(struct pipe_blend_state));
  430.    blend.rt[0].blend_enable = 0;
  431.    blend.rt[0].colormask = PIPE_MASK_RGBA;
  432.  
  433.    /* porter&duff src */
  434.    blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
  435.    blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
  436.    blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
  437.    blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
  438.  
  439.    cso_set_blend(port->r->cso, &blend);
  440. }
  441.  
  442.  
  443. static void
  444. bind_shaders(struct xorg_xv_port_priv *port)
  445. {
  446.    unsigned vs_traits = 0, fs_traits = 0;
  447.    struct xorg_shader shader;
  448.  
  449.    vs_traits |= VS_YUV;
  450.    fs_traits |= FS_YUV;
  451.  
  452.    shader = xorg_shaders_get(port->r->shaders, vs_traits, fs_traits);
  453.    cso_set_vertex_shader_handle(port->r->cso, shader.vs);
  454.    cso_set_fragment_shader_handle(port->r->cso, shader.fs);
  455. }
  456.  
  457. static void
  458. bind_samplers(struct xorg_xv_port_priv *port)
  459. {
  460.    struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
  461.    struct pipe_sampler_state sampler;
  462.    struct pipe_sampler_view **dst_views = port->yuv_views[port->current_set];
  463.  
  464.    memset(&sampler, 0, sizeof(struct pipe_sampler_state));
  465.  
  466.    sampler.wrap_s = PIPE_TEX_WRAP_CLAMP;
  467.    sampler.wrap_t = PIPE_TEX_WRAP_CLAMP;
  468.    sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
  469.    sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
  470.    sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
  471.    sampler.normalized_coords = 1;
  472.  
  473.    samplers[0] = &sampler;
  474.    samplers[1] = &sampler;
  475.    samplers[2] = &sampler;
  476.  
  477.  
  478.    cso_set_samplers(port->r->cso, PIPE_SHADER_FRAGMENT, 3,
  479.                     (const struct pipe_sampler_state **)samplers);
  480.    cso_set_sampler_views(port->r->cso, PIPE_SHADER_FRAGMENT, 3, dst_views);
  481. }
  482.  
  483. static int
  484. display_video(ScrnInfoPtr pScrn, struct xorg_xv_port_priv *pPriv, int id,
  485.               RegionPtr dstRegion,
  486.               int src_x, int src_y, int src_w, int src_h,
  487.               int dstX, int dstY, int dst_w, int dst_h,
  488.               PixmapPtr pPixmap)
  489. {
  490.    modesettingPtr ms = modesettingPTR(pScrn);
  491.    BoxPtr pbox;
  492.    int nbox;
  493.    int dxo, dyo;
  494.    Bool hdtv;
  495.    int x, y, w, h;
  496.    struct exa_pixmap_priv *dst;
  497.    struct pipe_surface *dst_surf = NULL;
  498.  
  499.    exaMoveInPixmap(pPixmap);
  500.    dst = exaGetPixmapDriverPrivate(pPixmap);
  501.  
  502.    /*debug_printf("display_video([%d, %d, %d, %d], [%d, %d, %d, %d])\n",
  503.      src_x, src_y, src_w, src_h, dstX, dstY, dst_w, dst_h);*/
  504.  
  505.    if (dst && !dst->tex) {
  506.         xorg_exa_set_shared_usage(pPixmap);
  507.         pScrn->pScreen->ModifyPixmapHeader(pPixmap, 0, 0, 0, 0, 0, NULL);
  508.    }
  509.  
  510.    if (!dst || !dst->tex)
  511.       XORG_FALLBACK("Xv destination %s", !dst ? "!dst" : "!dst->tex");
  512.  
  513.    dst_surf = xorg_gpu_surface(pPriv->r->pipe, dst);
  514.    hdtv = ((src_w >= RES_720P_X) && (src_h >= RES_720P_Y));
  515.  
  516. #ifdef COMPOSITE
  517.    REGION_TRANSLATE(pScrn->pScreen, dstRegion, -pPixmap->screen_x,
  518.                     -pPixmap->screen_y);
  519. #endif
  520.  
  521.    dxo = dstRegion->extents.x1;
  522.    dyo = dstRegion->extents.y1;
  523.  
  524.    pbox = REGION_RECTS(dstRegion);
  525.    nbox = REGION_NUM_RECTS(dstRegion);
  526.  
  527.    renderer_bind_destination(pPriv->r, dst_surf,
  528.                              dst_surf->width, dst_surf->height);
  529.  
  530.    bind_blend_state(pPriv);
  531.    bind_shaders(pPriv);
  532.    bind_samplers(pPriv);
  533.    setup_fs_video_constants(pPriv->r, hdtv);
  534.  
  535.    DamageDamageRegion(&pPixmap->drawable, dstRegion);
  536.  
  537.    while (nbox--) {
  538.       int box_x1 = pbox->x1;
  539.       int box_y1 = pbox->y1;
  540.       int box_x2 = pbox->x2;
  541.       int box_y2 = pbox->y2;
  542.       float diff_x = (float)src_w / (float)dst_w;
  543.       float diff_y = (float)src_h / (float)dst_h;
  544.       float offset_x = box_x1 - dstX;
  545.       float offset_y = box_y1 - dstY;
  546.       float offset_w;
  547.       float offset_h;
  548.  
  549. #ifdef COMPOSITE
  550.       offset_x += pPixmap->screen_x;
  551.       offset_y += pPixmap->screen_y;
  552. #endif
  553.  
  554.       x = box_x1;
  555.       y = box_y1;
  556.       w = box_x2 - box_x1;
  557.       h = box_y2 - box_y1;
  558.  
  559.       offset_w = dst_w - w;
  560.       offset_h = dst_h - h;
  561.  
  562.       draw_yuv(pPriv,
  563.                (float) src_x + offset_x*diff_x, (float) src_y + offset_y*diff_y,
  564.                (float) src_w - offset_w*diff_x, (float) src_h - offset_h*diff_y,
  565.                x, y, w, h);
  566.  
  567.       pbox++;
  568.    }
  569.    DamageRegionProcessPending(&pPixmap->drawable);
  570.  
  571.    pipe_surface_reference(&dst_surf, NULL);
  572.  
  573.    return TRUE;
  574. }
  575.  
  576. static int
  577. put_image(ScrnInfoPtr pScrn,
  578.           short src_x, short src_y,
  579.           short drw_x, short drw_y,
  580.           short src_w, short src_h,
  581.           short drw_w, short drw_h,
  582.           int id, unsigned char *buf,
  583.           short width, short height,
  584.           Bool sync, RegionPtr clipBoxes, pointer data,
  585.           DrawablePtr pDraw)
  586. {
  587.    struct xorg_xv_port_priv *pPriv = (struct xorg_xv_port_priv *) data;
  588.    ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
  589.    PixmapPtr pPixmap;
  590.    INT32 x1, x2, y1, y2;
  591.    BoxRec dstBox;
  592.    int ret;
  593.  
  594.    /* Clip */
  595.    x1 = src_x;
  596.    x2 = src_x + src_w;
  597.    y1 = src_y;
  598.    y2 = src_y + src_h;
  599.  
  600.    dstBox.x1 = drw_x;
  601.    dstBox.x2 = drw_x + drw_w;
  602.    dstBox.y1 = drw_y;
  603.    dstBox.y2 = drw_y + drw_h;
  604.  
  605.    if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
  606.                               width, height))
  607.       return Success;
  608.  
  609.    ret = check_yuv_textures(pPriv, width, height);
  610.  
  611.    if (ret)
  612.       return ret;
  613.  
  614.    copy_packed_data(pScrn, pPriv, id, buf,
  615.                     src_x, src_y, width, height);
  616.  
  617.    if (pDraw->type == DRAWABLE_WINDOW) {
  618.       pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr)pDraw);
  619.    } else {
  620.       pPixmap = (PixmapPtr)pDraw;
  621.    }
  622.  
  623.    display_video(pScrn, pPriv, id, clipBoxes,
  624.                  src_x, src_y, src_w, src_h,
  625.                  drw_x, drw_y,
  626.                  drw_w, drw_h, pPixmap);
  627.  
  628.    pPriv->current_set = (pPriv->current_set + 1) & 1;
  629.    return Success;
  630. }
  631.  
  632. static struct xorg_xv_port_priv *
  633. port_priv_create(struct xorg_renderer *r)
  634. {
  635.    struct xorg_xv_port_priv *priv = NULL;
  636.  
  637.    priv = calloc(1, sizeof(struct xorg_xv_port_priv));
  638.  
  639.    if (!priv)
  640.       return NULL;
  641.  
  642.    priv->r = r;
  643.  
  644.    REGION_NULL(pScreen, &priv->clip);
  645.  
  646.    debug_assert(priv && priv->r);
  647.  
  648.    return priv;
  649. }
  650.  
  651. static XF86VideoAdaptorPtr
  652. xorg_setup_textured_adapter(ScreenPtr pScreen)
  653. {
  654.    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
  655.    modesettingPtr ms = modesettingPTR(pScrn);
  656.    XF86VideoAdaptorPtr adapt;
  657.    XF86AttributePtr attrs;
  658.    DevUnion *dev_unions;
  659.    int nports = 16, i;
  660.    int nattributes;
  661.  
  662.    nattributes = NUM_TEXTURED_ATTRIBUTES;
  663.  
  664.    debug_assert(ms->exa);
  665.    debug_assert(ms->exa->renderer);
  666.  
  667.    adapt = calloc(1, sizeof(XF86VideoAdaptorRec));
  668.    dev_unions = calloc(nports, sizeof(DevUnion));
  669.    attrs = calloc(nattributes, sizeof(XF86AttributeRec));
  670.    if (adapt == NULL || dev_unions == NULL || attrs == NULL) {
  671.       free(adapt);
  672.       free(dev_unions);
  673.       free(attrs);
  674.       return NULL;
  675.    }
  676.  
  677.    adapt->type = XvWindowMask | XvInputMask | XvImageMask;
  678.    adapt->flags = 0;
  679.    adapt->name = "Gallium3D Textured Video";
  680.    adapt->nEncodings = 1;
  681.    adapt->pEncodings = DummyEncoding;
  682.    adapt->nFormats = NUM_FORMATS;
  683.    adapt->pFormats = Formats;
  684.    adapt->nPorts = 0;
  685.    adapt->pPortPrivates = dev_unions;
  686.    adapt->nAttributes = nattributes;
  687.    adapt->pAttributes = attrs;
  688.    memcpy(attrs, TexturedAttributes, nattributes * sizeof(XF86AttributeRec));
  689.    adapt->nImages = NUM_IMAGES;
  690.    adapt->pImages = Images;
  691.    adapt->PutVideo = NULL;
  692.    adapt->PutStill = NULL;
  693.    adapt->GetVideo = NULL;
  694.    adapt->GetStill = NULL;
  695.    adapt->StopVideo = stop_video;
  696.    adapt->SetPortAttribute = set_port_attribute;
  697.    adapt->GetPortAttribute = get_port_attribute;
  698.    adapt->QueryBestSize = query_best_size;
  699.    adapt->PutImage = put_image;
  700.    adapt->QueryImageAttributes = query_image_attributes;
  701.  
  702.    for (i = 0; i < nports; i++) {
  703.       struct xorg_xv_port_priv *priv =
  704.          port_priv_create(ms->exa->renderer);
  705.  
  706.       adapt->pPortPrivates[i].ptr = (pointer) (priv);
  707.       adapt->nPorts++;
  708.    }
  709.  
  710.    return adapt;
  711. }
  712.  
  713. void
  714. xorg_xv_init(ScreenPtr pScreen)
  715. {
  716.    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
  717.    /*modesettingPtr ms = modesettingPTR(pScrn);*/
  718.    XF86VideoAdaptorPtr *adaptors, *new_adaptors = NULL;
  719.    XF86VideoAdaptorPtr textured_adapter;
  720.    int num_adaptors;
  721.  
  722.    num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
  723.    new_adaptors = malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr *));
  724.    if (new_adaptors == NULL)
  725.       return;
  726.  
  727.    memcpy(new_adaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr));
  728.    adaptors = new_adaptors;
  729.  
  730.    /* Add the adaptors supported by our hardware.  First, set up the atoms
  731.     * that will be used by both output adaptors.
  732.     */
  733.    xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
  734.    xvContrast = MAKE_ATOM("XV_CONTRAST");
  735.  
  736.    textured_adapter = xorg_setup_textured_adapter(pScreen);
  737.  
  738.    debug_assert(textured_adapter);
  739.  
  740.    if (textured_adapter) {
  741.       adaptors[num_adaptors++] = textured_adapter;
  742.    }
  743.  
  744.    if (num_adaptors) {
  745.       xf86XVScreenInit(pScreen, adaptors, num_adaptors);
  746.       if (textured_adapter)
  747.          xorg_xvmc_init(pScreen, textured_adapter->name);
  748.    } else {
  749.       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
  750.                  "Disabling Xv because no adaptors could be initialized.\n");
  751.    }
  752.  
  753.    free(adaptors);
  754. }
  755.