<commit_before>#include "xorg_composite.h"

#include "xorg_exa_tgsi.h"

#include "cso_cache/cso_context.h"
#include "util/u_draw_quad.h"
#include "util/u_math.h"

#include "pipe/p_inlines.h"

struct xorg_composite_blend {
   int op:8;

   unsigned rgb_src_factor:5;    /**< PIPE_BLENDFACTOR_x */
   unsigned alpha_src_factor:5;  /**< PIPE_BLENDFACTOR_x */

   unsigned rgb_dst_factor:5;    /**< PIPE_BLENDFACTOR_x */
   unsigned alpha_dst_factor:5;  /**< PIPE_BLENDFACTOR_x */
};

#define BLEND_OP_OVER 3
static const struct xorg_composite_blend xorg_blends[] = {
   { PictOpClear,
     PIPE_BLENDFACTOR_CONST_COLOR, PIPE_BLENDFACTOR_CONST_ALPHA,
     PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO },

   { PictOpSrc,
     PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE,
     PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO },

   { PictOpDst,
     PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO,
     PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE },

   { PictOpOver,
     PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_ONE,
     PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA },

   { PictOpOverReverse,
     PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_ONE,
     PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA },
};


static INLINE void
pixel_to_float4(Pixel pixel, float *color)
{
   CARD32	    r, g, b, a;

   a = (pixel >> 24) & 0xff;
   r = (pixel >> 16) & 0xff;
   g = (pixel >>  8) & 0xff;
   b = (pixel >>  0) & 0xff;
   color[0] = ((float)r) / 255.;
   color[1] = ((float)g) / 255.;
   color[2] = ((float)b) / 255.;
   color[3] = ((float)a) / 255.;
}

static INLINE void
render_pixel_to_float4(PictFormatPtr format,
                       CARD32 pixel, float *color)
{
   CARD32	    r, g, b, a;

   debug_assert(format->type == PictTypeDirect);

   r = (pixel >> format->direct.red) & format->direct.redMask;
   g = (pixel >> format->direct.green) & format->direct.greenMask;
   b = (pixel >> format->direct.blue) & format->direct.blueMask;
   a = (pixel >> format->direct.alpha) & format->direct.alphaMask;
   color[0] = ((float)r) / ((float)format->direct.redMask);
   color[1] = ((float)g) / ((float)format->direct.greenMask);
   color[2] = ((float)b) / ((float)format->direct.blueMask);
   color[3] = ((float)a) / ((float)format->direct.alphaMask);
}

struct acceleration_info {
   int op : 16;
   int with_mask : 1;
   int component_alpha : 1;
};
static const struct acceleration_info accelerated_ops[] = {
   {PictOpClear,       1, 0},
   {PictOpSrc,         1, 0},
   {PictOpDst,         1, 0},
   {PictOpOver,        1, 0},
   {PictOpOverReverse, 1, 0},
   {PictOpIn,          1, 0},
   {PictOpInReverse,   1, 0},
   {PictOpOut,         1, 0},
   {PictOpOutReverse,  1, 0},
   {PictOpAtop,        1, 0},
   {PictOpAtopReverse, 1, 0},
   {PictOpXor,         1, 0},
   {PictOpAdd,         1, 0},
   {PictOpSaturate,    1, 0},
};

static struct xorg_composite_blend
blend_for_op(int op)
{
   const int num_blends =
      sizeof(xorg_blends)/sizeof(struct xorg_composite_blend);
   int i;

   for (i = 0; i < num_blends; ++i) {
      if (xorg_blends[i].op == op)
         return xorg_blends[i];
   }
   return xorg_blends[BLEND_OP_OVER];
}

static INLINE int
render_repeat_to_gallium(int mode)
{
   switch(mode) {
   case RepeatNone:
      return PIPE_TEX_WRAP_CLAMP;
   case RepeatNormal:
      return PIPE_TEX_WRAP_REPEAT;
   case RepeatReflect:
      return PIPE_TEX_WRAP_MIRROR_REPEAT;
   case RepeatPad:
      return PIPE_TEX_WRAP_CLAMP_TO_EDGE;
   default:
      debug_printf("Unsupported repeat mode\n");
   }
   return PIPE_TEX_WRAP_REPEAT;
}


static INLINE void
setup_vertex0(float vertex[2][4], float x, float y,
              float color[4])
{
   vertex[0][0] = x;
   vertex[0][1] = y;
   vertex[0][2] = 0.f; /*z*/
   vertex[0][3] = 1.f; /*w*/

   vertex[1][0] = color[0]; /*r*/
   vertex[1][1] = color[1]; /*g*/
   vertex[1][2] = color[2]; /*b*/
   vertex[1][3] = color[3]; /*a*/
}

static struct pipe_buffer *
setup_vertex_data0(struct exa_context *ctx,
                   int srcX, int srcY, int maskX, int maskY,
                   int dstX, int dstY, int width, int height)
{
   /* 1st vertex */
   setup_vertex0(ctx->vertices2[0], dstX, dstY,
                 ctx->solid_color);
   /* 2nd vertex */
   setup_vertex0(ctx->vertices2[1], dstX + width, dstY,
                 ctx->solid_color);
   /* 3rd vertex */
   setup_vertex0(ctx->vertices2[2], dstX + width, dstY + height,
                 ctx->solid_color);
   /* 4th vertex */
   setup_vertex0(ctx->vertices2[3], dstX, dstY + height,
                 ctx->solid_color);

   return pipe_user_buffer_create(ctx->pipe->screen,
                                  ctx->vertices2,
                                  sizeof(ctx->vertices2));
}

static INLINE void
setup_vertex1(float vertex[2][4], float x, float y, float s, float t)
{
   vertex[0][0] = x;
   vertex[0][1] = y;
   vertex[0][2] = 0.f; /*z*/
   vertex[0][3] = 1.f; /*w*/

   vertex[1][0] = s;   /*s*/
   vertex[1][1] = t;   /*t*/
   vertex[1][2] = 0.f; /*r*/
   vertex[1][3] = 1.f; /*q*/
}

static struct pipe_buffer *
setup_vertex_data1(struct exa_context *ctx,
                   int srcX, int srcY, int maskX, int maskY,
                   int dstX, int dstY, int width, int height)
{
   float s0, t0, s1, t1;
   struct pipe_texture *src = ctx->bound_textures[0];

   s0 = srcX / src->width[0];
   s1 = srcX + width / src->width[0];
   t0 = srcY / src->height[0];
   t1 = srcY + height / src->height[0];

   /* 1st vertex */
   setup_vertex1(ctx->vertices2[0], dstX, dstY,
                 s0, t0);
   /* 2nd vertex */
   setup_vertex1(ctx->vertices2[1], dstX + width, dstY,
                 s1, t0);
   /* 3rd vertex */
   setup_vertex1(ctx->vertices2[2], dstX + width, dstY + height,
                 s1, t1);
   /* 4th vertex */
   setup_vertex1(ctx->vertices2[3], dstX, dstY + height,
                 s0, t1);

   return pipe_user_buffer_create(ctx->pipe->screen,
                                  ctx->vertices2,
                                  sizeof(ctx->vertices2));
}

static struct pipe_buffer *
setup_vertex_data_tex(struct exa_context *ctx,
                      float x0, float y0, float x1, float y1,
                      float s0, float t0, float s1, float t1,
                      float z)
{
   /* 1st vertex */
   setup_vertex1(ctx->vertices2[0], x0, y0,
                 s0, t0);
   /* 2nd vertex */
   setup_vertex1(ctx->vertices2[1], x1, y0,
                 s1, t0);
   /* 3rd vertex */
   setup_vertex1(ctx->vertices2[2], x1, y1,
                 s1, t1);
   /* 4th vertex */
   setup_vertex1(ctx->vertices2[3], x0, y1,
                 s0, t1);

   return pipe_user_buffer_create(ctx->pipe->screen,
                                  ctx->vertices2,
                                  sizeof(ctx->vertices2));
}



static INLINE void
setup_vertex2(float vertex[3][4], float x, float y,
              float s0, float t0, float s1, float t1)
{
   vertex[0][0] = x;
   vertex[0][1] = y;
   vertex[0][2] = 0.f; /*z*/
   vertex[0][3] = 1.f; /*w*/

   vertex[1][0] = s0;  /*s*/
   vertex[1][1] = t0;  /*t*/
   vertex[1][2] = 0.f; /*r*/
   vertex[1][3] = 1.f; /*q*/

   vertex[2][0] = s1;  /*s*/
   vertex[2][1] = t1;  /*t*/
   vertex[2][2] = 0.f; /*r*/
   vertex[2][3] = 1.f; /*q*/
}

static struct pipe_buffer *
setup_vertex_data2(struct exa_context *ctx,
                   int srcX, int srcY, int maskX, int maskY,
                   int dstX, int dstY, int width, int height)
{
   float st0[4], st1[4];
   struct pipe_texture *src = ctx->bound_textures[0];
   struct pipe_texture *mask = ctx->bound_textures[0];

   st0[0] = srcX / src->width[0];
   st0[1] = srcY / src->height[0];
   st0[2] = srcX + width / src->width[0];
   st0[3] = srcY + height / src->height[0];

   st1[0] = maskX / mask->width[0];
   st1[1] = maskY / mask->height[0];
   st1[2] = maskX + width / mask->width[0];
   st1[3] = maskY + height / mask->height[0];

   /* 1st vertex */
   setup_vertex2(ctx->vertices3[0], dstX, dstY,
                 st0[0], st0[1], st1[0], st1[1]);
   /* 2nd vertex */
   setup_vertex2(ctx->vertices3[1], dstX + width, dstY,
                 st0[2], st0[1], st1[2], st1[1]);
   /* 3rd vertex */
   setup_vertex2(ctx->vertices3[2], dstX + width, dstY + height,
                 st0[2], st0[3], st1[2], st1[3]);
   /* 4th vertex */
   setup_vertex2(ctx->vertices3[3], dstX, dstY + height,
                 st0[0], st0[3], st1[0], st1[3]);

   return pipe_user_buffer_create(ctx->pipe->screen,
                                  ctx->vertices3,
                                  sizeof(ctx->vertices3));
}

boolean xorg_composite_accelerated(int op,
                                   PicturePtr pSrcPicture,
                                   PicturePtr pMaskPicture,
                                   PicturePtr pDstPicture)
{
   unsigned i;
   unsigned accel_ops_count =
      sizeof(accelerated_ops)/sizeof(struct acceleration_info);

   for (i = 0; i < accel_ops_count; ++i) {
      if (op == accelerated_ops[i].op) {
         /* Check for unsupported component alpha */
         if ((pSrcPicture->componentAlpha &&
              !accelerated_ops[i].component_alpha) ||
             (pMaskPicture &&
              (!accelerated_ops[i].with_mask ||
               (pMaskPicture->componentAlpha &&
                !accelerated_ops[i].component_alpha))))
            return FALSE;
         return TRUE;
      }
   }
   return FALSE;
}

static void
bind_clip_state(struct exa_context *exa)
{
}

static void
bind_framebuffer_state(struct exa_context *exa, struct exa_pixmap_priv *pDst)
{
   unsigned i;
   struct pipe_framebuffer_state state;
   struct pipe_surface *surface = exa_gpu_surface(exa, pDst);
   memset(&state, 0, sizeof(struct pipe_framebuffer_state));

   state.width  = pDst->tex->width[0];
   state.height = pDst->tex->height[0];

   state.nr_cbufs = 1;
   state.cbufs[0] = surface;
   for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
      state.cbufs[i] = 0;

   /* currently we don't use depth/stencil */
   state.zsbuf = 0;

   cso_set_framebuffer(exa->cso, &state);

   /* we do fire and forget for the framebuffer, this is the forget part */
   pipe_surface_reference(&surface, NULL);
}

enum AxisOrientation {
   Y0_BOTTOM,
   Y0_TOP
};

static void
set_viewport(struct exa_context *exa, int width, int height,
             enum AxisOrientation orientation)
{
   struct pipe_viewport_state viewport;
   float y_scale = (orientation == Y0_BOTTOM) ? -2.f : 2.f;

   viewport.scale[0] =  width / 2.f;
   viewport.scale[1] =  height / y_scale;
   viewport.scale[2] =  1.0;
   viewport.scale[3] =  1.0;
   viewport.translate[0] = width / 2.f;
   viewport.translate[1] = height / 2.f;
   viewport.translate[2] = 0.0;
   viewport.translate[3] = 0.0;

   cso_set_viewport(exa->cso, &viewport);
}

static void
bind_viewport_state(struct exa_context *exa, struct exa_pixmap_priv *pDst)
{
   int width = pDst->tex->width[0];
   int height = pDst->tex->height[0];

   /*debug_printf("Bind viewport (%d, %d)\n", width, height);*/

   set_viewport(exa, width, height, Y0_TOP);
}

static void
bind_blend_state(struct exa_context *exa, int op,
                 PicturePtr pSrcPicture, PicturePtr pMaskPicture)
{
   struct xorg_composite_blend blend_opt;
   struct pipe_blend_state blend;

   blend_opt = blend_for_op(op);

   memset(&blend, 0, sizeof(struct pipe_blend_state));
   blend.blend_enable = 1;
   blend.colormask |= PIPE_MASK_R;
   blend.colormask |= PIPE_MASK_G;
   blend.colormask |= PIPE_MASK_B;
   blend.colormask |= PIPE_MASK_A;

   blend.rgb_src_factor   = blend_opt.rgb_src_factor;
   blend.alpha_src_factor = blend_opt.alpha_src_factor;
   blend.rgb_dst_factor   = blend_opt.rgb_dst_factor;
   blend.alpha_dst_factor = blend_opt.alpha_dst_factor;

   cso_set_blend(exa->cso, &blend);
}

static void
bind_rasterizer_state(struct exa_context *exa)
{
   struct pipe_rasterizer_state raster;
   memset(&raster, 0, sizeof(struct pipe_rasterizer_state));
   raster.gl_rasterization_rules = 1;
   cso_set_rasterizer(exa->cso, &raster);
}

static void
bind_shaders(struct exa_context *exa, int op,
             PicturePtr pSrcPicture, PicturePtr pMaskPicture)
{
   unsigned vs_traits = 0, fs_traits = 0;
   struct xorg_shader shader;

   exa->has_solid_color = FALSE;

   if (pSrcPicture) {
      if (pSrcPicture->pSourcePict) {
         if (pSrcPicture->pSourcePict->type == SourcePictTypeSolidFill) {
            fs_traits |= FS_SOLID_FILL;
            vs_traits |= VS_SOLID_FILL;
            render_pixel_to_float4(pSrcPicture->pFormat,
                                   pSrcPicture->pSourcePict->solidFill.color,
                                   exa->solid_color);
            exa->has_solid_color = TRUE;
         } else {
            debug_assert("!gradients not supported");
         }
      } else {
         fs_traits |= FS_COMPOSITE;
         vs_traits |= VS_COMPOSITE;
      }
   }

   if (pMaskPicture) {
      vs_traits |= VS_MASK;
      fs_traits |= FS_MASK;
   }

   shader = xorg_shaders_get(exa->shaders, vs_traits, fs_traits);
   cso_set_vertex_shader_handle(exa->cso, shader.vs);
   cso_set_fragment_shader_handle(exa->cso, shader.fs);
}


static void
bind_samplers(struct exa_context *exa, int op,
              PicturePtr pSrcPicture, PicturePtr pMaskPicture,
              PicturePtr pDstPicture,
              struct exa_pixmap_priv *pSrc,
              struct exa_pixmap_priv *pMask,
              struct exa_pixmap_priv *pDst)
{
   struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];<commit_msg>st/xorg: Source-only pictures always have format PICT_a8r8g8b8.<commit_after>#include "xorg_composite.h"

#include "xorg_exa_tgsi.h"

#include "cso_cache/cso_context.h"
#include "util/u_draw_quad.h"
#include "util/u_math.h"

#include "pipe/p_inlines.h"

struct xorg_composite_blend {
   int op:8;

   unsigned rgb_src_factor:5;    /**< PIPE_BLENDFACTOR_x */
   unsigned alpha_src_factor:5;  /**< PIPE_BLENDFACTOR_x */

   unsigned rgb_dst_factor:5;    /**< PIPE_BLENDFACTOR_x */
   unsigned alpha_dst_factor:5;  /**< PIPE_BLENDFACTOR_x */
};

#define BLEND_OP_OVER 3
static const struct xorg_composite_blend xorg_blends[] = {
   { PictOpClear,
     PIPE_BLENDFACTOR_CONST_COLOR, PIPE_BLENDFACTOR_CONST_ALPHA,
     PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO },

   { PictOpSrc,
     PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE,
     PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO },

   { PictOpDst,
     PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO,
     PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE },

   { PictOpOver,
     PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_ONE,
     PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA },

   { PictOpOverReverse,
     PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_ONE,
     PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA },
};


static INLINE void
pixel_to_float4(Pixel pixel, float *color)
{
   CARD32	    r, g, b, a;

   a = (pixel >> 24) & 0xff;
   r = (pixel >> 16) & 0xff;
   g = (pixel >>  8) & 0xff;
   b = (pixel >>  0) & 0xff;
   color[0] = ((float)r) / 255.;
   color[1] = ((float)g) / 255.;
   color[2] = ((float)b) / 255.;
   color[3] = ((float)a) / 255.;
}

struct acceleration_info {
   int op : 16;
   int with_mask : 1;
   int component_alpha : 1;
};
static const struct acceleration_info accelerated_ops[] = {
   {PictOpClear,       1, 0},
   {PictOpSrc,         1, 0},
   {PictOpDst,         1, 0},
   {PictOpOver,        1, 0},
   {PictOpOverReverse, 1, 0},
   {PictOpIn,          1, 0},
   {PictOpInReverse,   1, 0},
   {PictOpOut,         1, 0},
   {PictOpOutReverse,  1, 0},
   {PictOpAtop,        1, 0},
   {PictOpAtopReverse, 1, 0},
   {PictOpXor,         1, 0},
   {PictOpAdd,         1, 0},
   {PictOpSaturate,    1, 0},
};

static struct xorg_composite_blend
blend_for_op(int op)
{
   const int num_blends =
      sizeof(xorg_blends)/sizeof(struct xorg_composite_blend);
   int i;

   for (i = 0; i < num_blends; ++i) {
      if (xorg_blends[i].op == op)
         return xorg_blends[i];
   }
   return xorg_blends[BLEND_OP_OVER];
}

static INLINE int
render_repeat_to_gallium(int mode)
{
   switch(mode) {
   case RepeatNone:
      return PIPE_TEX_WRAP_CLAMP;
   case RepeatNormal:
      return PIPE_TEX_WRAP_REPEAT;
   case RepeatReflect:
      return PIPE_TEX_WRAP_MIRROR_REPEAT;
   case RepeatPad:
      return PIPE_TEX_WRAP_CLAMP_TO_EDGE;
   default:
      debug_printf("Unsupported repeat mode\n");
   }
   return PIPE_TEX_WRAP_REPEAT;
}


static INLINE void
setup_vertex0(float vertex[2][4], float x, float y,
              float color[4])
{
   vertex[0][0] = x;
   vertex[0][1] = y;
   vertex[0][2] = 0.f; /*z*/
   vertex[0][3] = 1.f; /*w*/

   vertex[1][0] = color[0]; /*r*/
   vertex[1][1] = color[1]; /*g*/
   vertex[1][2] = color[2]; /*b*/
   vertex[1][3] = color[3]; /*a*/
}

static struct pipe_buffer *
setup_vertex_data0(struct exa_context *ctx,
                   int srcX, int srcY, int maskX, int maskY,
                   int dstX, int dstY, int width, int height)
{
   /* 1st vertex */
   setup_vertex0(ctx->vertices2[0], dstX, dstY,
                 ctx->solid_color);
   /* 2nd vertex */
   setup_vertex0(ctx->vertices2[1], dstX + width, dstY,
                 ctx->solid_color);
   /* 3rd vertex */
   setup_vertex0(ctx->vertices2[2], dstX + width, dstY + height,
                 ctx->solid_color);
   /* 4th vertex */
   setup_vertex0(ctx->vertices2[3], dstX, dstY + height,
                 ctx->solid_color);

   return pipe_user_buffer_create(ctx->pipe->screen,
                                  ctx->vertices2,
                                  sizeof(ctx->vertices2));
}

static INLINE void
setup_vertex1(float vertex[2][4], float x, float y, float s, float t)
{
   vertex[0][0] = x;
   vertex[0][1] = y;
   vertex[0][2] = 0.f; /*z*/
   vertex[0][3] = 1.f; /*w*/

   vertex[1][0] = s;   /*s*/
   vertex[1][1] = t;   /*t*/
   vertex[1][2] = 0.f; /*r*/
   vertex[1][3] = 1.f; /*q*/
}

static struct pipe_buffer *
setup_vertex_data1(struct exa_context *ctx,
                   int srcX, int srcY, int maskX, int maskY,
                   int dstX, int dstY, int width, int height)
{
   float s0, t0, s1, t1;
   struct pipe_texture *src = ctx->bound_textures[0];

   s0 = srcX / src->width[0];
   s1 = srcX + width / src->width[0];
   t0 = srcY / src->height[0];
   t1 = srcY + height / src->height[0];

   /* 1st vertex */
   setup_vertex1(ctx->vertices2[0], dstX, dstY,
                 s0, t0);
   /* 2nd vertex */
   setup_vertex1(ctx->vertices2[1], dstX + width, dstY,
                 s1, t0);
   /* 3rd vertex */
   setup_vertex1(ctx->vertices2[2], dstX + width, dstY + height,
                 s1, t1);
   /* 4th vertex */
   setup_vertex1(ctx->vertices2[3], dstX, dstY + height,
                 s0, t1);

   return pipe_user_buffer_create(ctx->pipe->screen,
                                  ctx->vertices2,
                                  sizeof(ctx->vertices2));
}

static struct pipe_buffer *
setup_vertex_data_tex(struct exa_context *ctx,
                      float x0, float y0, float x1, float y1,
                      float s0, float t0, float s1, float t1,
                      float z)
{
   /* 1st vertex */
   setup_vertex1(ctx->vertices2[0], x0, y0,
                 s0, t0);
   /* 2nd vertex */
   setup_vertex1(ctx->vertices2[1], x1, y0,
                 s1, t0);
   /* 3rd vertex */
   setup_vertex1(ctx->vertices2[2], x1, y1,
                 s1, t1);
   /* 4th vertex */
   setup_vertex1(ctx->vertices2[3], x0, y1,
                 s0, t1);

   return pipe_user_buffer_create(ctx->pipe->screen,
                                  ctx->vertices2,
                                  sizeof(ctx->vertices2));
}



static INLINE void
setup_vertex2(float vertex[3][4], float x, float y,
              float s0, float t0, float s1, float t1)
{
   vertex[0][0] = x;
   vertex[0][1] = y;
   vertex[0][2] = 0.f; /*z*/
   vertex[0][3] = 1.f; /*w*/

   vertex[1][0] = s0;  /*s*/
   vertex[1][1] = t0;  /*t*/
   vertex[1][2] = 0.f; /*r*/
   vertex[1][3] = 1.f; /*q*/

   vertex[2][0] = s1;  /*s*/
   vertex[2][1] = t1;  /*t*/
   vertex[2][2] = 0.f; /*r*/
   vertex[2][3] = 1.f; /*q*/
}

static struct pipe_buffer *
setup_vertex_data2(struct exa_context *ctx,
                   int srcX, int srcY, int maskX, int maskY,
                   int dstX, int dstY, int width, int height)
{
   float st0[4], st1[4];
   struct pipe_texture *src = ctx->bound_textures[0];
   struct pipe_texture *mask = ctx->bound_textures[0];

   st0[0] = srcX / src->width[0];
   st0[1] = srcY / src->height[0];
   st0[2] = srcX + width / src->width[0];
   st0[3] = srcY + height / src->height[0];

   st1[0] = maskX / mask->width[0];
   st1[1] = maskY / mask->height[0];
   st1[2] = maskX + width / mask->width[0];
   st1[3] = maskY + height / mask->height[0];

   /* 1st vertex */
   setup_vertex2(ctx->vertices3[0], dstX, dstY,
                 st0[0], st0[1], st1[0], st1[1]);
   /* 2nd vertex */
   setup_vertex2(ctx->vertices3[1], dstX + width, dstY,
                 st0[2], st0[1], st1[2], st1[1]);
   /* 3rd vertex */
   setup_vertex2(ctx->vertices3[2], dstX + width, dstY + height,
                 st0[2], st0[3], st1[2], st1[3]);
   /* 4th vertex */
   setup_vertex2(ctx->vertices3[3], dstX, dstY + height,
                 st0[0], st0[3], st1[0], st1[3]);

   return pipe_user_buffer_create(ctx->pipe->screen,
                                  ctx->vertices3,
                                  sizeof(ctx->vertices3));
}

boolean xorg_composite_accelerated(int op,
                                   PicturePtr pSrcPicture,
                                   PicturePtr pMaskPicture,
                                   PicturePtr pDstPicture)
{
   unsigned i;
   unsigned accel_ops_count =
      sizeof(accelerated_ops)/sizeof(struct acceleration_info);

   for (i = 0; i < accel_ops_count; ++i) {
      if (op == accelerated_ops[i].op) {
         /* Check for unsupported component alpha */
         if ((pSrcPicture->componentAlpha &&
              !accelerated_ops[i].component_alpha) ||
             (pMaskPicture &&
              (!accelerated_ops[i].with_mask ||
               (pMaskPicture->componentAlpha &&
                !accelerated_ops[i].component_alpha))))
            return FALSE;
         return TRUE;
      }
   }
   return FALSE;
}

static void
bind_clip_state(struct exa_context *exa)
{
}

static void
bind_framebuffer_state(struct exa_context *exa, struct exa_pixmap_priv *pDst)
{
   unsigned i;
   struct pipe_framebuffer_state state;
   struct pipe_surface *surface = exa_gpu_surface(exa, pDst);
   memset(&state, 0, sizeof(struct pipe_framebuffer_state));

   state.width  = pDst->tex->width[0];
   state.height = pDst->tex->height[0];

   state.nr_cbufs = 1;
   state.cbufs[0] = surface;
   for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
      state.cbufs[i] = 0;

   /* currently we don't use depth/stencil */
   state.zsbuf = 0;

   cso_set_framebuffer(exa->cso, &state);

   /* we do fire and forget for the framebuffer, this is the forget part */
   pipe_surface_reference(&surface, NULL);
}

enum AxisOrientation {
   Y0_BOTTOM,
   Y0_TOP
};

static void
set_viewport(struct exa_context *exa, int width, int height,
             enum AxisOrientation orientation)
{
   struct pipe_viewport_state viewport;
   float y_scale = (orientation == Y0_BOTTOM) ? -2.f : 2.f;

   viewport.scale[0] =  width / 2.f;
   viewport.scale[1] =  height / y_scale;
   viewport.scale[2] =  1.0;
   viewport.scale[3] =  1.0;
   viewport.translate[0] = width / 2.f;
   viewport.translate[1] = height / 2.f;
   viewport.translate[2] = 0.0;
   viewport.translate[3] = 0.0;

   cso_set_viewport(exa->cso, &viewport);
}

static void
bind_viewport_state(struct exa_context *exa, struct exa_pixmap_priv *pDst)
{
   int width = pDst->tex->width[0];
   int height = pDst->tex->height[0];

   /*debug_printf("Bind viewport (%d, %d)\n", width, height);*/

   set_viewport(exa, width, height, Y0_TOP);
}

static void
bind_blend_state(struct exa_context *exa, int op,
                 PicturePtr pSrcPicture, PicturePtr pMaskPicture)
{
   struct xorg_composite_blend blend_opt;
   struct pipe_blend_state blend;

   blend_opt = blend_for_op(op);

   memset(&blend, 0, sizeof(struct pipe_blend_state));
   blend.blend_enable = 1;
   blend.colormask |= PIPE_MASK_R;
   blend.colormask |= PIPE_MASK_G;
   blend.colormask |= PIPE_MASK_B;
   blend.colormask |= PIPE_MASK_A;

   blend.rgb_src_factor   = blend_opt.rgb_src_factor;
   blend.alpha_src_factor = blend_opt.alpha_src_factor;
   blend.rgb_dst_factor   = blend_opt.rgb_dst_factor;
   blend.alpha_dst_factor = blend_opt.alpha_dst_factor;

   cso_set_blend(exa->cso, &blend);
}

static void
bind_rasterizer_state(struct exa_context *exa)
{
   struct pipe_rasterizer_state raster;
   memset(&raster, 0, sizeof(struct pipe_rasterizer_state));
   raster.gl_rasterization_rules = 1;
   cso_set_rasterizer(exa->cso, &raster);
}

static void
bind_shaders(struct exa_context *exa, int op,
             PicturePtr pSrcPicture, PicturePtr pMaskPicture)
{
   unsigned vs_traits = 0, fs_traits = 0;
   struct xorg_shader shader;

   exa->has_solid_color = FALSE;

   if (pSrcPicture) {
      if (pSrcPicture->pSourcePict) {
         if (pSrcPicture->pSourcePict->type == SourcePictTypeSolidFill) {
            fs_traits |= FS_SOLID_FILL;
            vs_traits |= VS_SOLID_FILL;
            debug_assert(pSrcPicture->format == PICT_a8r8g8b8);
            pixel_to_float4(pSrcPicture->pSourcePict->solidFill.color,
                            exa->solid_color);
            exa->has_solid_color = TRUE;
         } else {
            debug_assert("!gradients not supported");
         }
      } else {
         fs_traits |= FS_COMPOSITE;
         vs_traits |= VS_COMPOSITE;
      }
   }

   if (pMaskPicture) {
      vs_traits |= VS_MASK;
      fs_traits |= FS_MASK;
   }

   shader = xorg_shaders_get(exa->shaders, vs_traits, fs_traits);
   cso_set_vertex_shader_handle(exa->cso, shader.vs);
   cso_set_fragment_shader_handle(exa->cso, shader.fs);
}


static void
bind_samplers(struct exa_context *exa, int op,
              PicturePtr pSrcPicture, PicturePtr pMaskPicture,
              PicturePtr pDstPicture,
              struct exa_pixmap_priv *pSrc,
              struct exa_pixmap_priv *pMask,
              struct exa_pixmap_priv *pDst)
{
   struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
{'fraction_non_alphanumeric': 0.1349804842926977, 'fraction_numerical': 0.029671454014930463, 'mean_word_length': 2.5233644859813085, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 194, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 24, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3863846', 'n_tokens_mistral': 10382, 'n_tokens_neox': 9961, 'n_words': 1952}