xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

glamor_xv.c (22537B)


      1 /*
      2  * Copyright © 2013 Red Hat
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     21  * IN THE SOFTWARE.
     22  *
     23  * Authors:
     24  *      Dave Airlie <airlied@redhat.com>
     25  *
     26  * some code is derived from the xf86-video-ati radeon driver, mainly
     27  * the calculations.
     28  */
     29 
     30 /** @file glamor_xv.c
     31  *
     32  * Xv acceleration implementation
     33  */
     34 
     35 #ifdef HAVE_DIX_CONFIG_H
     36 #include <dix-config.h>
     37 #endif
     38 
     39 #include "glamor_priv.h"
     40 #include "glamor_transform.h"
     41 #include "glamor_transfer.h"
     42 
     43 #include <X11/extensions/Xv.h>
     44 #include <fourcc.h>
     45 /* Reference color space transform data */
     46 typedef struct tagREF_TRANSFORM {
     47     float RefLuma;
     48     float RefRCb;
     49     float RefRCr;
     50     float RefGCb;
     51     float RefGCr;
     52     float RefBCb;
     53     float RefBCr;
     54 } REF_TRANSFORM;
     55 
     56 #define RTFSaturation(a)   (1.0 + ((a)*1.0)/1000.0)
     57 #define RTFBrightness(a)   (((a)*1.0)/2000.0)
     58 #define RTFIntensity(a)   (((a)*1.0)/2000.0)
     59 #define RTFContrast(a)   (1.0 + ((a)*1.0)/1000.0)
     60 #define RTFHue(a)   (((a)*3.1416)/1000.0)
     61 
     62 static const glamor_facet glamor_facet_xv_planar_2 = {
     63     .name = "xv_planar_2",
     64 
     65     .version = 120,
     66 
     67     .source_name = "v_texcoord0",
     68     .vs_vars = ("attribute vec2 position;\n"
     69                 "attribute vec2 v_texcoord0;\n"
     70                 "varying vec2 tcs;\n"),
     71     .vs_exec = (GLAMOR_POS(gl_Position, position)
     72                 "        tcs = v_texcoord0;\n"),
     73 
     74     .fs_vars = ("uniform sampler2D y_sampler;\n"
     75                 "uniform sampler2D u_sampler;\n"
     76                 "uniform vec4 offsetyco;\n"
     77                 "uniform vec4 ucogamma;\n"
     78                 "uniform vec4 vco;\n"
     79                 "varying vec2 tcs;\n"),
     80     .fs_exec = (
     81                 "        float sample;\n"
     82                 "        vec2 sample_uv;\n"
     83                 "        vec4 temp1;\n"
     84                 "        sample = texture2D(y_sampler, tcs).w;\n"
     85                 "        temp1.xyz = offsetyco.www * vec3(sample) + offsetyco.xyz;\n"
     86                 "        sample_uv = texture2D(u_sampler, tcs).xy;\n"
     87                 "        temp1.xyz = ucogamma.xyz * vec3(sample_uv.x) + temp1.xyz;\n"
     88                 "        temp1.xyz = clamp(vco.xyz * vec3(sample_uv.y) + temp1.xyz, 0.0, 1.0);\n"
     89                 "        temp1.w = 1.0;\n"
     90                 "        gl_FragColor = temp1;\n"
     91                 ),
     92 };
     93 
     94 static const glamor_facet glamor_facet_xv_planar_3 = {
     95     .name = "xv_planar_3",
     96 
     97     .version = 120,
     98 
     99     .source_name = "v_texcoord0",
    100     .vs_vars = ("attribute vec2 position;\n"
    101                 "attribute vec2 v_texcoord0;\n"
    102                 "varying vec2 tcs;\n"),
    103     .vs_exec = (GLAMOR_POS(gl_Position, position)
    104                 "        tcs = v_texcoord0;\n"),
    105 
    106     .fs_vars = ("uniform sampler2D y_sampler;\n"
    107                 "uniform sampler2D u_sampler;\n"
    108                 "uniform sampler2D v_sampler;\n"
    109                 "uniform vec4 offsetyco;\n"
    110                 "uniform vec4 ucogamma;\n"
    111                 "uniform vec4 vco;\n"
    112                 "varying vec2 tcs;\n"),
    113     .fs_exec = (
    114                 "        float sample;\n"
    115                 "        vec4 temp1;\n"
    116                 "        sample = texture2D(y_sampler, tcs).w;\n"
    117                 "        temp1.xyz = offsetyco.www * vec3(sample) + offsetyco.xyz;\n"
    118                 "        sample = texture2D(u_sampler, tcs).w;\n"
    119                 "        temp1.xyz = ucogamma.xyz * vec3(sample) + temp1.xyz;\n"
    120                 "        sample = texture2D(v_sampler, tcs).w;\n"
    121                 "        temp1.xyz = clamp(vco.xyz * vec3(sample) + temp1.xyz, 0.0, 1.0);\n"
    122                 "        temp1.w = 1.0;\n"
    123                 "        gl_FragColor = temp1;\n"
    124                 ),
    125 };
    126 
    127 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
    128 
    129 XvAttributeRec glamor_xv_attributes[] = {
    130     {XvSettable | XvGettable, -1000, 1000, (char *)"XV_BRIGHTNESS"},
    131     {XvSettable | XvGettable, -1000, 1000, (char *)"XV_CONTRAST"},
    132     {XvSettable | XvGettable, -1000, 1000, (char *)"XV_SATURATION"},
    133     {XvSettable | XvGettable, -1000, 1000, (char *)"XV_HUE"},
    134     {XvSettable | XvGettable, 0, 1, (char *)"XV_COLORSPACE"},
    135     {0, 0, 0, NULL}
    136 };
    137 int glamor_xv_num_attributes = ARRAY_SIZE(glamor_xv_attributes) - 1;
    138 
    139 Atom glamorBrightness, glamorContrast, glamorSaturation, glamorHue,
    140     glamorColorspace, glamorGamma;
    141 
    142 XvImageRec glamor_xv_images[] = {
    143     XVIMAGE_YV12,
    144     XVIMAGE_I420,
    145     XVIMAGE_NV12
    146 };
    147 int glamor_xv_num_images = ARRAY_SIZE(glamor_xv_images);
    148 
    149 static void
    150 glamor_init_xv_shader(ScreenPtr screen, int id)
    151 {
    152     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
    153     GLint sampler_loc;
    154     const glamor_facet *glamor_facet_xv_planar = NULL;
    155 
    156     switch (id) {
    157     case FOURCC_YV12:
    158     case FOURCC_I420:
    159         glamor_facet_xv_planar = &glamor_facet_xv_planar_3;
    160         break;
    161     case FOURCC_NV12:
    162         glamor_facet_xv_planar = &glamor_facet_xv_planar_2;
    163         break;
    164     default:
    165         break;
    166     }
    167 
    168     glamor_build_program(screen,
    169                          &glamor_priv->xv_prog,
    170                          glamor_facet_xv_planar, NULL, NULL, NULL);
    171 
    172     glUseProgram(glamor_priv->xv_prog.prog);
    173     sampler_loc = glGetUniformLocation(glamor_priv->xv_prog.prog, "y_sampler");
    174     glUniform1i(sampler_loc, 0);
    175     sampler_loc = glGetUniformLocation(glamor_priv->xv_prog.prog, "u_sampler");
    176     glUniform1i(sampler_loc, 1);
    177 
    178     switch (id) {
    179     case FOURCC_YV12:
    180     case FOURCC_I420:
    181         sampler_loc = glGetUniformLocation(glamor_priv->xv_prog.prog, "v_sampler");
    182         glUniform1i(sampler_loc, 2);
    183         break;
    184     case FOURCC_NV12:
    185         break;
    186     default:
    187         break;
    188     }
    189 
    190 }
    191 
    192 #define ClipValue(v,min,max) ((v) < (min) ? (min) : (v) > (max) ? (max) : (v))
    193 
    194 void
    195 glamor_xv_stop_video(glamor_port_private *port_priv)
    196 {
    197 }
    198 
    199 static void
    200 glamor_xv_free_port_data(glamor_port_private *port_priv)
    201 {
    202     int i;
    203 
    204     for (i = 0; i < 3; i++) {
    205         if (port_priv->src_pix[i]) {
    206             glamor_destroy_pixmap(port_priv->src_pix[i]);
    207             port_priv->src_pix[i] = NULL;
    208         }
    209     }
    210     RegionUninit(&port_priv->clip);
    211     RegionNull(&port_priv->clip);
    212 }
    213 
    214 int
    215 glamor_xv_set_port_attribute(glamor_port_private *port_priv,
    216                              Atom attribute, INT32 value)
    217 {
    218     if (attribute == glamorBrightness)
    219         port_priv->brightness = ClipValue(value, -1000, 1000);
    220     else if (attribute == glamorHue)
    221         port_priv->hue = ClipValue(value, -1000, 1000);
    222     else if (attribute == glamorContrast)
    223         port_priv->contrast = ClipValue(value, -1000, 1000);
    224     else if (attribute == glamorSaturation)
    225         port_priv->saturation = ClipValue(value, -1000, 1000);
    226     else if (attribute == glamorGamma)
    227         port_priv->gamma = ClipValue(value, 100, 10000);
    228     else if (attribute == glamorColorspace)
    229         port_priv->transform_index = ClipValue(value, 0, 1);
    230     else
    231         return BadMatch;
    232     return Success;
    233 }
    234 
    235 int
    236 glamor_xv_get_port_attribute(glamor_port_private *port_priv,
    237                              Atom attribute, INT32 *value)
    238 {
    239     if (attribute == glamorBrightness)
    240         *value = port_priv->brightness;
    241     else if (attribute == glamorHue)
    242         *value = port_priv->hue;
    243     else if (attribute == glamorContrast)
    244         *value = port_priv->contrast;
    245     else if (attribute == glamorSaturation)
    246         *value = port_priv->saturation;
    247     else if (attribute == glamorGamma)
    248         *value = port_priv->gamma;
    249     else if (attribute == glamorColorspace)
    250         *value = port_priv->transform_index;
    251     else
    252         return BadMatch;
    253 
    254     return Success;
    255 }
    256 
    257 int
    258 glamor_xv_query_image_attributes(int id,
    259                                  unsigned short *w, unsigned short *h,
    260                                  int *pitches, int *offsets)
    261 {
    262     int size = 0, tmp;
    263 
    264     if (offsets)
    265         offsets[0] = 0;
    266     switch (id) {
    267     case FOURCC_YV12:
    268     case FOURCC_I420:
    269         *w = ALIGN(*w, 2);
    270         *h = ALIGN(*h, 2);
    271         size = ALIGN(*w, 4);
    272         if (pitches)
    273             pitches[0] = size;
    274         size *= *h;
    275         if (offsets)
    276             offsets[1] = size;
    277         tmp = ALIGN(*w >> 1, 4);
    278         if (pitches)
    279             pitches[1] = pitches[2] = tmp;
    280         tmp *= (*h >> 1);
    281         size += tmp;
    282         if (offsets)
    283             offsets[2] = size;
    284         size += tmp;
    285         break;
    286     case FOURCC_NV12:
    287         *w = ALIGN(*w, 2);
    288         *h = ALIGN(*h, 2);
    289         size = ALIGN(*w, 4);
    290         if (pitches)
    291             pitches[0] = size;
    292         size *= *h;
    293         if (offsets)
    294             offsets[1] = offsets[2] = size;
    295         tmp = ALIGN(*w, 4);
    296         if (pitches)
    297             pitches[1] = pitches[2] = tmp;
    298         tmp *= (*h >> 1);
    299         size += tmp;
    300         break;
    301     }
    302     return size;
    303 }
    304 
    305 /* Parameters for ITU-R BT.601 and ITU-R BT.709 colour spaces
    306    note the difference to the parameters used in overlay are due
    307    to 10bit vs. float calcs */
    308 static REF_TRANSFORM trans[2] = {
    309     {1.1643, 0.0, 1.5960, -0.3918, -0.8129, 2.0172, 0.0},       /* BT.601 */
    310     {1.1643, 0.0, 1.7927, -0.2132, -0.5329, 2.1124, 0.0}        /* BT.709 */
    311 };
    312 
    313 void
    314 glamor_xv_render(glamor_port_private *port_priv, int id)
    315 {
    316     ScreenPtr screen = port_priv->pPixmap->drawable.pScreen;
    317     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
    318     PixmapPtr pixmap = port_priv->pPixmap;
    319     glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
    320     glamor_pixmap_private *src_pixmap_priv[3];
    321     BoxPtr box = REGION_RECTS(&port_priv->clip);
    322     int nBox = REGION_NUM_RECTS(&port_priv->clip);
    323     GLfloat src_xscale[3], src_yscale[3];
    324     int i;
    325     const float Loff = -0.0627;
    326     const float Coff = -0.502;
    327     float uvcosf, uvsinf;
    328     float yco;
    329     float uco[3], vco[3], off[3];
    330     float bright, cont, gamma;
    331     int ref = port_priv->transform_index;
    332     GLint uloc;
    333     GLfloat *v;
    334     char *vbo_offset;
    335     int dst_box_index;
    336 
    337     if (!glamor_priv->xv_prog.prog)
    338         glamor_init_xv_shader(screen, id);
    339 
    340     cont = RTFContrast(port_priv->contrast);
    341     bright = RTFBrightness(port_priv->brightness);
    342     gamma = (float) port_priv->gamma / 1000.0;
    343     uvcosf = RTFSaturation(port_priv->saturation) * cos(RTFHue(port_priv->hue));
    344     uvsinf = RTFSaturation(port_priv->saturation) * sin(RTFHue(port_priv->hue));
    345 /* overlay video also does pre-gamma contrast/sat adjust, should we? */
    346 
    347     yco = trans[ref].RefLuma * cont;
    348     uco[0] = -trans[ref].RefRCr * uvsinf;
    349     uco[1] = trans[ref].RefGCb * uvcosf - trans[ref].RefGCr * uvsinf;
    350     uco[2] = trans[ref].RefBCb * uvcosf;
    351     vco[0] = trans[ref].RefRCr * uvcosf;
    352     vco[1] = trans[ref].RefGCb * uvsinf + trans[ref].RefGCr * uvcosf;
    353     vco[2] = trans[ref].RefBCb * uvsinf;
    354     off[0] = Loff * yco + Coff * (uco[0] + vco[0]) + bright;
    355     off[1] = Loff * yco + Coff * (uco[1] + vco[1]) + bright;
    356     off[2] = Loff * yco + Coff * (uco[2] + vco[2]) + bright;
    357     gamma = 1.0;
    358 
    359     glamor_set_alu(screen, GXcopy);
    360 
    361     for (i = 0; i < 3; i++) {
    362         if (port_priv->src_pix[i]) {
    363             src_pixmap_priv[i] =
    364                 glamor_get_pixmap_private(port_priv->src_pix[i]);
    365             pixmap_priv_get_scale(src_pixmap_priv[i], &src_xscale[i],
    366                                   &src_yscale[i]);
    367         } else {
    368            src_pixmap_priv[i] = NULL;
    369         }
    370     }
    371     glamor_make_current(glamor_priv);
    372     glUseProgram(glamor_priv->xv_prog.prog);
    373 
    374     uloc = glGetUniformLocation(glamor_priv->xv_prog.prog, "offsetyco");
    375     glUniform4f(uloc, off[0], off[1], off[2], yco);
    376     uloc = glGetUniformLocation(glamor_priv->xv_prog.prog, "ucogamma");
    377     glUniform4f(uloc, uco[0], uco[1], uco[2], gamma);
    378     uloc = glGetUniformLocation(glamor_priv->xv_prog.prog, "vco");
    379     glUniform4f(uloc, vco[0], vco[1], vco[2], 0);
    380 
    381     glActiveTexture(GL_TEXTURE0);
    382     glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[0]->fbo->tex);
    383     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    384     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    385     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    386     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    387 
    388     glActiveTexture(GL_TEXTURE1);
    389     glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[1]->fbo->tex);
    390     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    391     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    392     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    393     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    394 
    395     switch (id) {
    396     case FOURCC_YV12:
    397     case FOURCC_I420:
    398         glActiveTexture(GL_TEXTURE2);
    399         glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[2]->fbo->tex);
    400         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    401         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    402         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    403         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    404         break;
    405     case FOURCC_NV12:
    406         break;
    407     default:
    408         break;
    409     }
    410 
    411     glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
    412     glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
    413 
    414     glEnable(GL_SCISSOR_TEST);
    415 
    416     v = glamor_get_vbo_space(screen, 3 * 4 * sizeof(GLfloat), &vbo_offset);
    417 
    418     /* Set up a single primitive covering the area being drawn.  We'll
    419      * clip it to port_priv->clip using GL scissors instead of just
    420      * emitting a GL_QUAD per box, because this way we hopefully avoid
    421      * diagonal tearing between the two triangles used to rasterize a
    422      * GL_QUAD.
    423      */
    424     i = 0;
    425     v[i++] = port_priv->drw_x;
    426     v[i++] = port_priv->drw_y;
    427 
    428     v[i++] = port_priv->drw_x + port_priv->dst_w * 2;
    429     v[i++] = port_priv->drw_y;
    430 
    431     v[i++] = port_priv->drw_x;
    432     v[i++] = port_priv->drw_y + port_priv->dst_h * 2;
    433 
    434     v[i++] = t_from_x_coord_x(src_xscale[0], port_priv->src_x);
    435     v[i++] = t_from_x_coord_y(src_yscale[0], port_priv->src_y);
    436 
    437     v[i++] = t_from_x_coord_x(src_xscale[0], port_priv->src_x +
    438                               port_priv->src_w * 2);
    439     v[i++] = t_from_x_coord_y(src_yscale[0], port_priv->src_y);
    440 
    441     v[i++] = t_from_x_coord_x(src_xscale[0], port_priv->src_x);
    442     v[i++] = t_from_x_coord_y(src_yscale[0], port_priv->src_y +
    443                               port_priv->src_h * 2);
    444 
    445     glVertexAttribPointer(GLAMOR_VERTEX_POS, 2,
    446                           GL_FLOAT, GL_FALSE,
    447                           2 * sizeof(float), vbo_offset);
    448 
    449     glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2,
    450                           GL_FLOAT, GL_FALSE,
    451                           2 * sizeof(float), vbo_offset + 6 * sizeof(GLfloat));
    452 
    453     glamor_put_vbo_space(screen);
    454 
    455     /* Now draw our big triangle, clipped to each of the clip boxes. */
    456     glamor_pixmap_loop(pixmap_priv, dst_box_index) {
    457         int dst_off_x, dst_off_y;
    458 
    459         glamor_set_destination_drawable(port_priv->pDraw,
    460                                         dst_box_index,
    461                                         FALSE, FALSE,
    462                                         glamor_priv->xv_prog.matrix_uniform,
    463                                         &dst_off_x, &dst_off_y);
    464 
    465         for (i = 0; i < nBox; i++) {
    466             int dstx, dsty, dstw, dsth;
    467 
    468             dstx = box[i].x1 + dst_off_x;
    469             dsty = box[i].y1 + dst_off_y;
    470             dstw = box[i].x2 - box[i].x1;
    471             dsth = box[i].y2 - box[i].y1;
    472 
    473             glScissor(dstx, dsty, dstw, dsth);
    474             glDrawArrays(GL_TRIANGLE_FAN, 0, 3);
    475         }
    476     }
    477     glDisable(GL_SCISSOR_TEST);
    478 
    479     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
    480     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
    481 
    482     DamageDamageRegion(port_priv->pDraw, &port_priv->clip);
    483 
    484     glamor_xv_free_port_data(port_priv);
    485 }
    486 
    487 int
    488 glamor_xv_put_image(glamor_port_private *port_priv,
    489                     DrawablePtr pDrawable,
    490                     short src_x, short src_y,
    491                     short drw_x, short drw_y,
    492                     short src_w, short src_h,
    493                     short drw_w, short drw_h,
    494                     int id,
    495                     unsigned char *buf,
    496                     short width,
    497                     short height,
    498                     Bool sync,
    499                     RegionPtr clipBoxes)
    500 {
    501     ScreenPtr pScreen = pDrawable->pScreen;
    502     glamor_screen_private *glamor_priv = glamor_get_screen_private(pScreen);
    503     int srcPitch, srcPitch2;
    504     int top, nlines;
    505     int s2offset, s3offset, tmp;
    506     BoxRec full_box, half_box;
    507 
    508     s2offset = s3offset = srcPitch2 = 0;
    509 
    510     if (!port_priv->src_pix[0] ||
    511         (width != port_priv->src_pix_w || height != port_priv->src_pix_h) ||
    512         (port_priv->src_pix[2] && id == FOURCC_NV12) ||
    513         (!port_priv->src_pix[2] && id != FOURCC_NV12)) {
    514         int i;
    515 
    516         if (glamor_priv->xv_prog.prog) {
    517             glDeleteProgram(glamor_priv->xv_prog.prog);
    518             glamor_priv->xv_prog.prog = 0;
    519         }
    520 
    521         for (i = 0; i < 3; i++)
    522             if (port_priv->src_pix[i])
    523                 glamor_destroy_pixmap(port_priv->src_pix[i]);
    524 
    525         port_priv->src_pix[0] =
    526             glamor_create_pixmap(pScreen, width, height, 8,
    527                                  GLAMOR_CREATE_FBO_NO_FBO);
    528 
    529         switch (id) {
    530         case FOURCC_YV12:
    531         case FOURCC_I420:
    532             port_priv->src_pix[1] =
    533                 glamor_create_pixmap(pScreen, width >> 1, height >> 1, 8,
    534                                      GLAMOR_CREATE_FBO_NO_FBO);
    535             port_priv->src_pix[2] =
    536                 glamor_create_pixmap(pScreen, width >> 1, height >> 1, 8,
    537                                      GLAMOR_CREATE_FBO_NO_FBO);
    538             if (!port_priv->src_pix[2])
    539                 return BadAlloc;
    540             break;
    541         case FOURCC_NV12:
    542             port_priv->src_pix[1] =
    543                 glamor_create_pixmap(pScreen, width >> 1, height >> 1, 16,
    544                                      GLAMOR_CREATE_FBO_NO_FBO |
    545                                      GLAMOR_CREATE_FORMAT_CBCR);
    546             port_priv->src_pix[2] = NULL;
    547             break;
    548         default:
    549             return BadMatch;
    550         }
    551 
    552         port_priv->src_pix_w = width;
    553         port_priv->src_pix_h = height;
    554 
    555         if (!port_priv->src_pix[0] || !port_priv->src_pix[1])
    556             return BadAlloc;
    557     }
    558 
    559     top = (src_y) & ~1;
    560     nlines = (src_y + src_h) - top;
    561 
    562     switch (id) {
    563     case FOURCC_YV12:
    564     case FOURCC_I420:
    565         srcPitch = ALIGN(width, 4);
    566         srcPitch2 = ALIGN(width >> 1, 4);
    567         s2offset = srcPitch * height;
    568         s3offset = s2offset + (srcPitch2 * ((height + 1) >> 1));
    569         s2offset += ((top >> 1) * srcPitch2);
    570         s3offset += ((top >> 1) * srcPitch2);
    571         if (id == FOURCC_YV12) {
    572             tmp = s2offset;
    573             s2offset = s3offset;
    574             s3offset = tmp;
    575         }
    576 
    577         full_box.x1 = 0;
    578         full_box.y1 = 0;
    579         full_box.x2 = width;
    580         full_box.y2 = nlines;
    581 
    582         half_box.x1 = 0;
    583         half_box.y1 = 0;
    584         half_box.x2 = width >> 1;
    585         half_box.y2 = (nlines + 1) >> 1;
    586 
    587         glamor_upload_boxes(port_priv->src_pix[0], &full_box, 1,
    588                             0, 0, 0, 0,
    589                             buf + (top * srcPitch), srcPitch);
    590 
    591         glamor_upload_boxes(port_priv->src_pix[1], &half_box, 1,
    592                             0, 0, 0, 0,
    593                             buf + s2offset, srcPitch2);
    594 
    595         glamor_upload_boxes(port_priv->src_pix[2], &half_box, 1,
    596                             0, 0, 0, 0,
    597                             buf + s3offset, srcPitch2);
    598         break;
    599     case FOURCC_NV12:
    600         srcPitch = ALIGN(width, 4);
    601         s2offset = srcPitch * height;
    602         s2offset += ((top >> 1) * srcPitch);
    603 
    604         full_box.x1 = 0;
    605         full_box.y1 = 0;
    606         full_box.x2 = width;
    607         full_box.y2 = nlines;
    608 
    609         half_box.x1 = 0;
    610         half_box.y1 = 0;
    611         half_box.x2 = width;
    612         half_box.y2 = (nlines + 1) >> 1;
    613 
    614         glamor_upload_boxes(port_priv->src_pix[0], &full_box, 1,
    615                             0, 0, 0, 0,
    616                             buf + (top * srcPitch), srcPitch);
    617 
    618         glamor_upload_boxes(port_priv->src_pix[1], &half_box, 1,
    619                             0, 0, 0, 0,
    620                             buf + s2offset, srcPitch);
    621         break;
    622     default:
    623         return BadMatch;
    624     }
    625 
    626     if (pDrawable->type == DRAWABLE_WINDOW)
    627         port_priv->pPixmap = pScreen->GetWindowPixmap((WindowPtr) pDrawable);
    628     else
    629         port_priv->pPixmap = (PixmapPtr) pDrawable;
    630 
    631     RegionCopy(&port_priv->clip, clipBoxes);
    632 
    633     port_priv->src_x = src_x;
    634     port_priv->src_y = src_y - top;
    635     port_priv->src_w = src_w;
    636     port_priv->src_h = src_h;
    637     port_priv->dst_w = drw_w;
    638     port_priv->dst_h = drw_h;
    639     port_priv->drw_x = drw_x;
    640     port_priv->drw_y = drw_y;
    641     port_priv->w = width;
    642     port_priv->h = height;
    643     port_priv->pDraw = pDrawable;
    644     glamor_xv_render(port_priv, id);
    645     return Success;
    646 }
    647 
    648 void
    649 glamor_xv_init_port(glamor_port_private *port_priv)
    650 {
    651     port_priv->brightness = 0;
    652     port_priv->contrast = 0;
    653     port_priv->saturation = 0;
    654     port_priv->hue = 0;
    655     port_priv->gamma = 1000;
    656     port_priv->transform_index = 0;
    657 
    658     REGION_NULL(pScreen, &port_priv->clip);
    659 }
    660 
    661 void
    662 glamor_xv_core_init(ScreenPtr screen)
    663 {
    664     glamorBrightness = MAKE_ATOM("XV_BRIGHTNESS");
    665     glamorContrast = MAKE_ATOM("XV_CONTRAST");
    666     glamorSaturation = MAKE_ATOM("XV_SATURATION");
    667     glamorHue = MAKE_ATOM("XV_HUE");
    668     glamorGamma = MAKE_ATOM("XV_GAMMA");
    669     glamorColorspace = MAKE_ATOM("XV_COLORSPACE");
    670 }