Home | History | Annotate | Download | only in xorg
      1 #include "xorg_composite.h"
      2 
      3 #include "xorg_renderer.h"
      4 #include "xorg_exa_tgsi.h"
      5 
      6 #include "cso_cache/cso_context.h"
      7 #include "util/u_format.h"
      8 #include "util/u_sampler.h"
      9 
     10 
     11 /*XXX also in Xrender.h but the including it here breaks compilition */
     12 #define XFixedToDouble(f)    (((double) (f)) / 65536.)
     13 
     14 struct xorg_composite_blend {
     15    int op : 8;
     16 
     17    unsigned alpha_dst : 4;
     18    unsigned alpha_src : 4;
     19 
     20    unsigned rgb_src : 8;    /**< PIPE_BLENDFACTOR_x */
     21    unsigned rgb_dst : 8;    /**< PIPE_BLENDFACTOR_x */
     22 };
     23 
     24 #define BLEND_OP_OVER 3
     25 static const struct xorg_composite_blend xorg_blends[] = {
     26    { PictOpClear,
     27      0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO},
     28    { PictOpSrc,
     29      0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ZERO},
     30    { PictOpDst,
     31      0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ONE},
     32    { PictOpOver,
     33      0, 1, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_INV_SRC_ALPHA},
     34    { PictOpOverReverse,
     35      1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ONE},
     36    { PictOpIn,
     37      1, 0, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_ZERO},
     38    { PictOpInReverse,
     39      0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_SRC_ALPHA},
     40    { PictOpOut,
     41      1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ZERO},
     42    { PictOpOutReverse,
     43      0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_INV_SRC_ALPHA},
     44    { PictOpAtop,
     45      1, 1, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA},
     46    { PictOpAtopReverse,
     47      1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_SRC_ALPHA},
     48    { PictOpXor,
     49      1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA},
     50    { PictOpAdd,
     51      0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE},
     52 };
     53 
     54 
     55 static INLINE void
     56 pixel_to_float4(Pixel pixel, float *color, enum pipe_format format)
     57 {
     58    const struct util_format_description *format_desc;
     59    uint8_t packed[4];
     60 
     61    format_desc = util_format_description(format);
     62    packed[0] = pixel;
     63    packed[1] = pixel >> 8;
     64    packed[2] = pixel >> 16;
     65    packed[3] = pixel >> 24;
     66    format_desc->unpack_rgba_float(color, 0, packed, 0, 1, 1);
     67 }
     68 
     69 static boolean
     70 blend_for_op(struct xorg_composite_blend *blend,
     71              int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
     72              PicturePtr pDstPicture)
     73 {
     74    const int num_blends =
     75       sizeof(xorg_blends)/sizeof(struct xorg_composite_blend);
     76    int i;
     77    boolean supported = FALSE;
     78 
     79    /* our default in case something goes wrong */
     80    *blend = xorg_blends[BLEND_OP_OVER];
     81 
     82    for (i = 0; i < num_blends; ++i) {
     83       if (xorg_blends[i].op == op) {
     84          *blend = xorg_blends[i];
     85          supported = TRUE;
     86       }
     87    }
     88 
     89    /* If there's no dst alpha channel, adjust the blend op so that we'll treat
     90     * it as always 1. */
     91    if (pDstPicture &&
     92        PICT_FORMAT_A(pDstPicture->format) == 0 && blend->alpha_dst) {
     93       if (blend->rgb_src == PIPE_BLENDFACTOR_DST_ALPHA)
     94          blend->rgb_src = PIPE_BLENDFACTOR_ONE;
     95       else if (blend->rgb_src == PIPE_BLENDFACTOR_INV_DST_ALPHA)
     96          blend->rgb_src = PIPE_BLENDFACTOR_ZERO;
     97    }
     98 
     99    /* If the source alpha is being used, then we should only be in a case where
    100     * the source blend factor is 0, and the source blend value is the mask
    101     * channels multiplied by the source picture's alpha. */
    102    if (pMaskPicture && pMaskPicture->componentAlpha &&
    103        PICT_FORMAT_RGB(pMaskPicture->format) && blend->alpha_src) {
    104       if (blend->rgb_dst == PIPE_BLENDFACTOR_SRC_ALPHA) {
    105          blend->rgb_dst = PIPE_BLENDFACTOR_SRC_COLOR;
    106       } else if (blend->rgb_dst == PIPE_BLENDFACTOR_INV_SRC_ALPHA) {
    107          blend->rgb_dst = PIPE_BLENDFACTOR_INV_SRC_COLOR;
    108       }
    109    }
    110 
    111    return supported;
    112 }
    113 
    114 static INLINE int
    115 render_repeat_to_gallium(int mode)
    116 {
    117    switch(mode) {
    118    case RepeatNone:
    119       return PIPE_TEX_WRAP_CLAMP_TO_BORDER;
    120    case RepeatNormal:
    121       return PIPE_TEX_WRAP_REPEAT;
    122    case RepeatReflect:
    123       return PIPE_TEX_WRAP_MIRROR_REPEAT;
    124    case RepeatPad:
    125       return PIPE_TEX_WRAP_CLAMP_TO_EDGE;
    126    default:
    127       debug_printf("Unsupported repeat mode\n");
    128    }
    129    return PIPE_TEX_WRAP_REPEAT;
    130 }
    131 
    132 static INLINE boolean
    133 render_filter_to_gallium(int xrender_filter, int *out_filter)
    134 {
    135 
    136    switch (xrender_filter) {
    137    case PictFilterNearest:
    138       *out_filter = PIPE_TEX_FILTER_NEAREST;
    139       break;
    140    case PictFilterBilinear:
    141       *out_filter = PIPE_TEX_FILTER_LINEAR;
    142       break;
    143    case PictFilterFast:
    144       *out_filter = PIPE_TEX_FILTER_NEAREST;
    145       break;
    146    case PictFilterGood:
    147       *out_filter = PIPE_TEX_FILTER_LINEAR;
    148       break;
    149    case PictFilterBest:
    150       *out_filter = PIPE_TEX_FILTER_LINEAR;
    151       break;
    152    case PictFilterConvolution:
    153       *out_filter = PIPE_TEX_FILTER_NEAREST;
    154       return FALSE;
    155    default:
    156       debug_printf("Unknown xrender filter\n");
    157       *out_filter = PIPE_TEX_FILTER_NEAREST;
    158       return FALSE;
    159    }
    160 
    161    return TRUE;
    162 }
    163 
    164 static boolean is_filter_accelerated(PicturePtr pic)
    165 {
    166    int filter;
    167    if (pic && !render_filter_to_gallium(pic->filter, &filter))
    168        return FALSE;
    169    return TRUE;
    170 }
    171 
    172 boolean xorg_composite_accelerated(int op,
    173                                    PicturePtr pSrcPicture,
    174                                    PicturePtr pMaskPicture,
    175                                    PicturePtr pDstPicture)
    176 {
    177    ScreenPtr pScreen = pDstPicture->pDrawable->pScreen;
    178    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    179    modesettingPtr ms = modesettingPTR(pScrn);
    180    struct xorg_composite_blend blend;
    181 
    182    if (!is_filter_accelerated(pSrcPicture) ||
    183        !is_filter_accelerated(pMaskPicture)) {
    184       XORG_FALLBACK("Unsupported Xrender filter");
    185    }
    186 
    187    if (pSrcPicture->pSourcePict) {
    188       if (pSrcPicture->pSourcePict->type != SourcePictTypeSolidFill)
    189          XORG_FALLBACK("Gradients not enabled (haven't been well tested)");
    190    }
    191 
    192    if (blend_for_op(&blend, op,
    193                     pSrcPicture, pMaskPicture, pDstPicture)) {
    194       /* Check for component alpha */
    195       if (pMaskPicture && pMaskPicture->componentAlpha &&
    196           PICT_FORMAT_RGB(pMaskPicture->format)) {
    197          if (blend.alpha_src && blend.rgb_src != PIPE_BLENDFACTOR_ZERO) {
    198             XORG_FALLBACK("Component alpha not supported with source "
    199                           "alpha and source value blending. (op=%d)",
    200                           op);
    201          }
    202       }
    203 
    204       return TRUE;
    205    }
    206    XORG_FALLBACK("Unsupported composition operation = %d", op);
    207 }
    208 
    209 static void
    210 bind_blend_state(struct exa_context *exa, int op,
    211                  PicturePtr pSrcPicture,
    212                  PicturePtr pMaskPicture,
    213                  PicturePtr pDstPicture)
    214 {
    215    struct xorg_composite_blend blend_opt;
    216    struct pipe_blend_state blend;
    217 
    218    blend_for_op(&blend_opt, op, pSrcPicture, pMaskPicture, pDstPicture);
    219 
    220    memset(&blend, 0, sizeof(struct pipe_blend_state));
    221    blend.rt[0].blend_enable = 1;
    222    blend.rt[0].colormask = PIPE_MASK_RGBA;
    223 
    224    blend.rt[0].rgb_src_factor   = blend_opt.rgb_src;
    225    blend.rt[0].alpha_src_factor = blend_opt.rgb_src;
    226    blend.rt[0].rgb_dst_factor   = blend_opt.rgb_dst;
    227    blend.rt[0].alpha_dst_factor = blend_opt.rgb_dst;
    228 
    229    cso_set_blend(exa->renderer->cso, &blend);
    230 }
    231 
    232 static unsigned
    233 picture_format_fixups(struct exa_pixmap_priv *pSrc, PicturePtr pSrcPicture, boolean mask,
    234                       PicturePtr pDstPicture)
    235 {
    236    boolean set_alpha = FALSE;
    237    boolean swizzle = FALSE;
    238    unsigned ret = 0;
    239 
    240    if (pSrc && pSrc->picture_format == pSrcPicture->format) {
    241       if (pSrc->picture_format == PICT_a8) {
    242          if (mask)
    243             return FS_MASK_LUMINANCE;
    244          else if (pDstPicture->format != PICT_a8) {
    245             /* if both dst and src are luminance then
    246              * we don't want to swizzle the alpha (X) of the
    247              * source into W component of the dst because
    248              * it will break our destination */
    249             return FS_SRC_LUMINANCE;
    250          }
    251       }
    252       return 0;
    253    }
    254 
    255    if (pSrc && pSrc->picture_format != PICT_a8r8g8b8) {
    256       assert(!"can not handle formats");
    257       return 0;
    258    }
    259 
    260    /* pSrc->picture_format == PICT_a8r8g8b8 */
    261    switch (pSrcPicture->format) {
    262    case PICT_x8b8g8r8:
    263    case PICT_b8g8r8:
    264       set_alpha = TRUE; /* fall trough */
    265    case PICT_a8b8g8r8:
    266       swizzle = TRUE;
    267       break;
    268    case PICT_x8r8g8b8:
    269    case PICT_r8g8b8:
    270       set_alpha = TRUE; /* fall through */
    271    case PICT_a8r8g8b8:
    272       break;
    273 #ifdef PICT_TYPE_BGRA
    274    case PICT_b8g8r8a8:
    275    case PICT_b8g8r8x8:
    276    case PICT_a2r10g10b10:
    277    case PICT_x2r10g10b10:
    278    case PICT_a2b10g10r10:
    279    case PICT_x2b10g10r10:
    280 #endif
    281    default:
    282       assert(!"can not handle formats");
    283       return 0;
    284    }
    285 
    286    if (set_alpha)
    287       ret |= mask ? FS_MASK_SET_ALPHA : FS_SRC_SET_ALPHA;
    288    if (swizzle)
    289       ret |= mask ? FS_MASK_SWIZZLE_RGB : FS_SRC_SWIZZLE_RGB;
    290 
    291    return ret;
    292 }
    293 
    294 static void
    295 bind_shaders(struct exa_context *exa, int op,
    296              PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture,
    297              struct exa_pixmap_priv *pSrc, struct exa_pixmap_priv *pMask)
    298 {
    299    unsigned vs_traits = 0, fs_traits = 0;
    300    struct xorg_shader shader;
    301 
    302    exa->has_solid_color = FALSE;
    303 
    304    if (pSrcPicture) {
    305       if (pSrcPicture->repeatType == RepeatNone && pSrcPicture->transform)
    306          fs_traits |= FS_SRC_REPEAT_NONE;
    307 
    308       if (pSrcPicture->pSourcePict) {
    309          if (pSrcPicture->pSourcePict->type == SourcePictTypeSolidFill) {
    310             fs_traits |= FS_SOLID_FILL;
    311             vs_traits |= VS_SOLID_FILL;
    312             debug_assert(pSrcPicture->format == PICT_a8r8g8b8);
    313             pixel_to_float4(pSrcPicture->pSourcePict->solidFill.color,
    314                             exa->solid_color, PIPE_FORMAT_B8G8R8A8_UNORM);
    315             exa->has_solid_color = TRUE;
    316          } else {
    317             debug_assert("!gradients not supported");
    318          }
    319       } else {
    320          fs_traits |= FS_COMPOSITE;
    321          vs_traits |= VS_COMPOSITE;
    322       }
    323 
    324       fs_traits |= picture_format_fixups(pSrc, pSrcPicture, FALSE, pDstPicture);
    325    }
    326 
    327    if (pMaskPicture) {
    328       vs_traits |= VS_MASK;
    329       fs_traits |= FS_MASK;
    330       if (pMaskPicture->repeatType == RepeatNone && pMaskPicture->transform)
    331          fs_traits |= FS_MASK_REPEAT_NONE;
    332       if (pMaskPicture->componentAlpha) {
    333          struct xorg_composite_blend blend;
    334          blend_for_op(&blend, op,
    335                       pSrcPicture, pMaskPicture, NULL);
    336          if (blend.alpha_src) {
    337             fs_traits |= FS_CA_SRCALPHA;
    338          } else
    339             fs_traits |= FS_CA_FULL;
    340       }
    341 
    342       fs_traits |= picture_format_fixups(pMask, pMaskPicture, TRUE, pDstPicture);
    343    }
    344 
    345    shader = xorg_shaders_get(exa->renderer->shaders, vs_traits, fs_traits);
    346    cso_set_vertex_shader_handle(exa->renderer->cso, shader.vs);
    347    cso_set_fragment_shader_handle(exa->renderer->cso, shader.fs);
    348 }
    349 
    350 static void
    351 bind_samplers(struct exa_context *exa, int op,
    352               PicturePtr pSrcPicture, PicturePtr pMaskPicture,
    353               PicturePtr pDstPicture,
    354               struct exa_pixmap_priv *pSrc,
    355               struct exa_pixmap_priv *pMask,
    356               struct exa_pixmap_priv *pDst)
    357 {
    358    struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS] = {0};
    359    struct pipe_sampler_state src_sampler, mask_sampler;
    360    struct pipe_sampler_view view_templ;
    361    struct pipe_sampler_view *src_view;
    362    struct pipe_context *pipe = exa->pipe;
    363 
    364    exa->num_bound_samplers = 0;
    365 
    366    memset(&src_sampler, 0, sizeof(struct pipe_sampler_state));
    367    memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state));
    368 
    369    if (pSrcPicture && pSrc) {
    370       if (exa->has_solid_color) {
    371          debug_assert(!"solid color with textures");
    372          samplers[0] = NULL;
    373          pipe_sampler_view_reference(&exa->bound_sampler_views[0], NULL);
    374       } else {
    375          unsigned src_wrap = render_repeat_to_gallium(
    376             pSrcPicture->repeatType);
    377          int filter;
    378 
    379          render_filter_to_gallium(pSrcPicture->filter, &filter);
    380 
    381          src_sampler.wrap_s = src_wrap;
    382          src_sampler.wrap_t = src_wrap;
    383          src_sampler.min_img_filter = filter;
    384          src_sampler.mag_img_filter = filter;
    385          src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
    386          src_sampler.normalized_coords = 1;
    387          samplers[0] = &src_sampler;
    388          exa->num_bound_samplers = 1;
    389          u_sampler_view_default_template(&view_templ,
    390                                          pSrc->tex,
    391                                          pSrc->tex->format);
    392          src_view = pipe->create_sampler_view(pipe, pSrc->tex, &view_templ);
    393          pipe_sampler_view_reference(&exa->bound_sampler_views[0], NULL);
    394          exa->bound_sampler_views[0] = src_view;
    395       }
    396    }
    397 
    398    if (pMaskPicture && pMask) {
    399       unsigned mask_wrap = render_repeat_to_gallium(
    400          pMaskPicture->repeatType);
    401       int filter;
    402 
    403       render_filter_to_gallium(pMaskPicture->filter, &filter);
    404 
    405       mask_sampler.wrap_s = mask_wrap;
    406       mask_sampler.wrap_t = mask_wrap;
    407       mask_sampler.min_img_filter = filter;
    408       mask_sampler.mag_img_filter = filter;
    409       src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
    410       mask_sampler.normalized_coords = 1;
    411       samplers[1] = &mask_sampler;
    412       exa->num_bound_samplers = 2;
    413       u_sampler_view_default_template(&view_templ,
    414                                       pMask->tex,
    415                                       pMask->tex->format);
    416       src_view = pipe->create_sampler_view(pipe, pMask->tex, &view_templ);
    417       pipe_sampler_view_reference(&exa->bound_sampler_views[1], NULL);
    418       exa->bound_sampler_views[1] = src_view;
    419    }
    420 
    421    cso_set_samplers(exa->renderer->cso, PIPE_SHADER_FRAGMENT,
    422                     exa->num_bound_samplers,
    423                     (const struct pipe_sampler_state **)samplers);
    424    cso_set_sampler_views(exa->renderer->cso, PIPE_SHADER_FRAGMENT,
    425                          exa->num_bound_samplers,
    426                          exa->bound_sampler_views);
    427 }
    428 
    429 
    430 
    431 static INLINE boolean matrix_from_pict_transform(PictTransform *trans, float *matrix)
    432 {
    433    if (!trans)
    434       return FALSE;
    435 
    436    matrix[0] = XFixedToDouble(trans->matrix[0][0]);
    437    matrix[3] = XFixedToDouble(trans->matrix[0][1]);
    438    matrix[6] = XFixedToDouble(trans->matrix[0][2]);
    439 
    440    matrix[1] = XFixedToDouble(trans->matrix[1][0]);
    441    matrix[4] = XFixedToDouble(trans->matrix[1][1]);
    442    matrix[7] = XFixedToDouble(trans->matrix[1][2]);
    443 
    444    matrix[2] = XFixedToDouble(trans->matrix[2][0]);
    445    matrix[5] = XFixedToDouble(trans->matrix[2][1]);
    446    matrix[8] = XFixedToDouble(trans->matrix[2][2]);
    447 
    448    return TRUE;
    449 }
    450 
    451 static void
    452 setup_transforms(struct  exa_context *exa,
    453                  PicturePtr pSrcPicture, PicturePtr pMaskPicture)
    454 {
    455    PictTransform *src_t = NULL;
    456    PictTransform *mask_t = NULL;
    457 
    458    if (pSrcPicture)
    459       src_t = pSrcPicture->transform;
    460    if (pMaskPicture)
    461       mask_t = pMaskPicture->transform;
    462 
    463    exa->transform.has_src  =
    464       matrix_from_pict_transform(src_t, exa->transform.src);
    465    exa->transform.has_mask =
    466       matrix_from_pict_transform(mask_t, exa->transform.mask);
    467 }
    468 
    469 boolean xorg_composite_bind_state(struct exa_context *exa,
    470                                   int op,
    471                                   PicturePtr pSrcPicture,
    472                                   PicturePtr pMaskPicture,
    473                                   PicturePtr pDstPicture,
    474                                   struct exa_pixmap_priv *pSrc,
    475                                   struct exa_pixmap_priv *pMask,
    476                                   struct exa_pixmap_priv *pDst)
    477 {
    478    struct pipe_surface *dst_surf = xorg_gpu_surface(exa->pipe, pDst);
    479 
    480    renderer_bind_destination(exa->renderer, dst_surf,
    481                              pDst->width,
    482                              pDst->height);
    483 
    484    bind_blend_state(exa, op, pSrcPicture, pMaskPicture, pDstPicture);
    485    bind_shaders(exa, op, pSrcPicture, pMaskPicture, pDstPicture, pSrc, pMask);
    486    bind_samplers(exa, op, pSrcPicture, pMaskPicture,
    487                  pDstPicture, pSrc, pMask, pDst);
    488 
    489    setup_transforms(exa, pSrcPicture, pMaskPicture);
    490 
    491    if (exa->num_bound_samplers == 0 ) { /* solid fill */
    492       renderer_begin_solid(exa->renderer);
    493    } else {
    494       renderer_begin_textures(exa->renderer,
    495                               exa->num_bound_samplers);
    496    }
    497 
    498 
    499    pipe_surface_reference(&dst_surf, NULL);
    500    return TRUE;
    501 }
    502 
    503 void xorg_composite(struct exa_context *exa,
    504                     struct exa_pixmap_priv *dst,
    505                     int srcX, int srcY, int maskX, int maskY,
    506                     int dstX, int dstY, int width, int height)
    507 {
    508    if (exa->num_bound_samplers == 0 ) { /* solid fill */
    509       renderer_solid(exa->renderer,
    510                      dstX, dstY, dstX + width, dstY + height,
    511                      exa->solid_color);
    512    } else {
    513       int pos[6] = {srcX, srcY, maskX, maskY, dstX, dstY};
    514       float *src_matrix = NULL;
    515       float *mask_matrix = NULL;
    516 
    517       if (exa->transform.has_src)
    518          src_matrix = exa->transform.src;
    519       if (exa->transform.has_mask)
    520          mask_matrix = exa->transform.mask;
    521 
    522       renderer_texture(exa->renderer,
    523                        pos, width, height,
    524                        exa->bound_sampler_views,
    525                        exa->num_bound_samplers,
    526                        src_matrix, mask_matrix);
    527    }
    528 }
    529 
    530 boolean xorg_solid_bind_state(struct exa_context *exa,
    531                               struct exa_pixmap_priv *pixmap,
    532                               Pixel fg)
    533 {
    534    struct pipe_surface *dst_surf = xorg_gpu_surface(exa->pipe, pixmap);
    535    unsigned vs_traits, fs_traits;
    536    struct xorg_shader shader;
    537 
    538    pixel_to_float4(fg, exa->solid_color, pixmap->tex->format);
    539    exa->has_solid_color = TRUE;
    540 
    541 #if 0
    542    debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n",
    543                 (fg >> 24) & 0xff, (fg >> 16) & 0xff,
    544                 (fg >> 8) & 0xff,  (fg >> 0) & 0xff,
    545                 exa->solid_color[0], exa->solid_color[1],
    546                 exa->solid_color[2], exa->solid_color[3]);
    547 #endif
    548 
    549    vs_traits = VS_SOLID_FILL;
    550    fs_traits = FS_SOLID_FILL;
    551 
    552    renderer_bind_destination(exa->renderer, dst_surf,
    553                              pixmap->width, pixmap->height);
    554    bind_blend_state(exa, PictOpSrc, NULL, NULL, NULL);
    555    cso_set_samplers(exa->renderer->cso, PIPE_SHADER_FRAGMENT, 0, NULL);
    556    cso_set_sampler_views(exa->renderer->cso, PIPE_SHADER_FRAGMENT, 0, NULL);
    557 
    558    shader = xorg_shaders_get(exa->renderer->shaders, vs_traits, fs_traits);
    559    cso_set_vertex_shader_handle(exa->renderer->cso, shader.vs);
    560    cso_set_fragment_shader_handle(exa->renderer->cso, shader.fs);
    561 
    562    renderer_begin_solid(exa->renderer);
    563 
    564    pipe_surface_reference(&dst_surf, NULL);
    565    return TRUE;
    566 }
    567 
    568 void xorg_solid(struct exa_context *exa,
    569                 struct exa_pixmap_priv *pixmap,
    570                 int x0, int y0, int x1, int y1)
    571 {
    572    renderer_solid(exa->renderer,
    573                   x0, y0, x1, y1, exa->solid_color);
    574 }
    575 
    576 void
    577 xorg_composite_done(struct exa_context *exa)
    578 {
    579    renderer_draw_flush(exa->renderer);
    580 
    581    exa->transform.has_src = FALSE;
    582    exa->transform.has_mask = FALSE;
    583    exa->has_solid_color = FALSE;
    584    exa->num_bound_samplers = 0;
    585 }
    586