Subversion Repositories Kolibri OS

Rev

Rev 3280 | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright © 2012 Intel Corporation
  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 FROM,
  20.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21.  * SOFTWARE.
  22.  *
  23.  * Authors:
  24.  *    Chris Wilson <chris@chris-wilson.co.uk>
  25.  *
  26.  */
  27.  
  28. #ifdef HAVE_CONFIG_H
  29. #include "config.h"
  30. #endif
  31.  
  32. #include "sna.h"
  33. #include "sna_render.h"
  34. #include "sna_render_inline.h"
  35. #include "gen4_vertex.h"
  36.  
  37. #ifndef sse2
  38. #define sse2
  39. #endif
  40.  
  41. void gen4_vertex_flush(struct sna *sna)
  42. {
  43.     DBG(("%s[%x] = %d\n", __FUNCTION__,
  44.          4*sna->render.vertex_offset,
  45.          sna->render.vertex_index - sna->render.vertex_start));
  46.  
  47.     assert(sna->render.vertex_offset);
  48.     assert(sna->render.vertex_index > sna->render.vertex_start);
  49.  
  50.     sna->kgem.batch[sna->render.vertex_offset] =
  51.         sna->render.vertex_index - sna->render.vertex_start;
  52.     sna->render.vertex_offset = 0;
  53. }
  54.  
  55. int gen4_vertex_finish(struct sna *sna)
  56. {
  57.     struct kgem_bo *bo;
  58.     unsigned int i;
  59.     unsigned hint, size;
  60.  
  61.     DBG(("%s: used=%d / %d\n", __FUNCTION__,
  62.          sna->render.vertex_used, sna->render.vertex_size));
  63.     assert(sna->render.vertex_offset == 0);
  64.     assert(sna->render.vertex_used);
  65.  
  66.         sna_vertex_wait__locked(&sna->render);
  67.  
  68.     /* Note: we only need dword alignment (currently) */
  69.  
  70.     bo = sna->render.vbo;
  71.     if (bo) {
  72.         for (i = 0; i < sna->render.nvertex_reloc; i++) {
  73.             DBG(("%s: reloc[%d] = %d\n", __FUNCTION__,
  74.                  i, sna->render.vertex_reloc[i]));
  75.  
  76.             sna->kgem.batch[sna->render.vertex_reloc[i]] =
  77.                 kgem_add_reloc(&sna->kgem,
  78.                            sna->render.vertex_reloc[i], bo,
  79.                            I915_GEM_DOMAIN_VERTEX << 16,
  80.                            0);
  81.         }
  82.  
  83.         assert(!sna->render.active);
  84.         sna->render.nvertex_reloc = 0;
  85.         sna->render.vertex_used = 0;
  86.         sna->render.vertex_index = 0;
  87.         sna->render.vbo = NULL;
  88.         sna->render.vb_id = 0;
  89.  
  90.         kgem_bo_destroy(&sna->kgem, bo);
  91.     }
  92.  
  93.     hint = CREATE_GTT_MAP;
  94.     if (bo)
  95.         hint |= CREATE_CACHED | CREATE_NO_THROTTLE;
  96.  
  97.     size = 256*1024;
  98.     assert(!sna->render.active);
  99.     sna->render.vertices = NULL;
  100.     sna->render.vbo = kgem_create_linear(&sna->kgem, size, hint);
  101.     while (sna->render.vbo == NULL && size > 16*1024) {
  102.         size /= 2;
  103.         sna->render.vbo = kgem_create_linear(&sna->kgem, size, hint);
  104.     }
  105.     if (sna->render.vbo == NULL)
  106.         sna->render.vbo = kgem_create_linear(&sna->kgem,
  107.                              256*1024, CREATE_GTT_MAP);
  108.     if (sna->render.vbo)
  109.         sna->render.vertices = kgem_bo_map(&sna->kgem, sna->render.vbo);
  110.     if (sna->render.vertices == NULL) {
  111.         if (sna->render.vbo) {
  112.             kgem_bo_destroy(&sna->kgem, sna->render.vbo);
  113.             sna->render.vbo = NULL;
  114.         }
  115.         sna->render.vertices = sna->render.vertex_data;
  116.         sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data);
  117.         return 0;
  118.     }
  119.  
  120.     if (sna->render.vertex_used) {
  121.         DBG(("%s: copying initial buffer x %d to handle=%d\n",
  122.              __FUNCTION__,
  123.              sna->render.vertex_used,
  124.              sna->render.vbo->handle));
  125.         assert(sizeof(float)*sna->render.vertex_used <=
  126.                __kgem_bo_size(sna->render.vbo));
  127.         memcpy(sna->render.vertices,
  128.                sna->render.vertex_data,
  129.                sizeof(float)*sna->render.vertex_used);
  130.     }
  131.  
  132.     size = __kgem_bo_size(sna->render.vbo)/4;
  133.     if (size >= UINT16_MAX)
  134.         size = UINT16_MAX - 1;
  135.  
  136.     DBG(("%s: create vbo handle=%d, size=%d\n",
  137.          __FUNCTION__, sna->render.vbo->handle, size));
  138.  
  139.     sna->render.vertex_size = size;
  140.     return sna->render.vertex_size - sna->render.vertex_used;
  141. }
  142.  
  143. void gen4_vertex_close(struct sna *sna)
  144. {
  145.     struct kgem_bo *bo, *free_bo = NULL;
  146.     unsigned int i, delta = 0;
  147.  
  148.     assert(sna->render.vertex_offset == 0);
  149.     if (!sna->render.vb_id)
  150.         return;
  151.  
  152.     DBG(("%s: used=%d, vbo active? %d, vb=%x, nreloc=%d\n",
  153.          __FUNCTION__, sna->render.vertex_used, sna->render.vbo ? sna->render.vbo->handle : 0,
  154.          sna->render.vb_id, sna->render.nvertex_reloc));
  155.  
  156.     assert(!sna->render.active);
  157.  
  158.     bo = sna->render.vbo;
  159.     if (bo) {
  160.         if (sna->render.vertex_size - sna->render.vertex_used < 64) {
  161.             DBG(("%s: discarding vbo (full), handle=%d\n", __FUNCTION__, sna->render.vbo->handle));
  162.             sna->render.vbo = NULL;
  163.             sna->render.vertices = sna->render.vertex_data;
  164.             sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data);
  165.             free_bo = bo;
  166.         } else if (IS_CPU_MAP(bo->map) && !sna->kgem.has_llc) {
  167.             DBG(("%s: converting CPU map to GTT\n", __FUNCTION__));
  168.             sna->render.vertices =
  169.                 kgem_bo_map__gtt(&sna->kgem, sna->render.vbo);
  170.             if (sna->render.vertices == NULL) {
  171.                 sna->render.vbo = NULL;
  172.                 sna->render.vertices = sna->render.vertex_data;
  173.                 sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data);
  174.                 free_bo = bo;
  175.             }
  176.  
  177.         }
  178.     } else {
  179.         if (sna->kgem.nbatch + sna->render.vertex_used <= sna->kgem.surface) {
  180.             DBG(("%s: copy to batch: %d @ %d\n", __FUNCTION__,
  181.                  sna->render.vertex_used, sna->kgem.nbatch));
  182.             memcpy(sna->kgem.batch + sna->kgem.nbatch,
  183.                    sna->render.vertex_data,
  184.                    sna->render.vertex_used * 4);
  185.             delta = sna->kgem.nbatch * 4;
  186.             bo = NULL;
  187.             sna->kgem.nbatch += sna->render.vertex_used;
  188.         } else {
  189.             bo = kgem_create_linear(&sna->kgem,
  190.                         4*sna->render.vertex_used,
  191.                         CREATE_NO_THROTTLE);
  192.             if (bo && !kgem_bo_write(&sna->kgem, bo,
  193.                          sna->render.vertex_data,
  194.                          4*sna->render.vertex_used)) {
  195.                 kgem_bo_destroy(&sna->kgem, bo);
  196.                 bo = NULL;
  197.             }
  198.             DBG(("%s: new vbo: %d\n", __FUNCTION__,
  199.                  sna->render.vertex_used));
  200.             free_bo = bo;
  201.         }
  202.     }
  203.  
  204.     assert(sna->render.nvertex_reloc);
  205.     for (i = 0; i < sna->render.nvertex_reloc; i++) {
  206.         DBG(("%s: reloc[%d] = %d\n", __FUNCTION__,
  207.              i, sna->render.vertex_reloc[i]));
  208.  
  209.         sna->kgem.batch[sna->render.vertex_reloc[i]] =
  210.             kgem_add_reloc(&sna->kgem,
  211.                        sna->render.vertex_reloc[i], bo,
  212.                        I915_GEM_DOMAIN_VERTEX << 16,
  213.                        delta);
  214.     }
  215.     sna->render.nvertex_reloc = 0;
  216.     sna->render.vb_id = 0;
  217.  
  218.     if (sna->render.vbo == NULL) {
  219.         assert(!sna->render.active);
  220.         sna->render.vertex_used = 0;
  221.         sna->render.vertex_index = 0;
  222.         assert(sna->render.vertices == sna->render.vertex_data);
  223.         assert(sna->render.vertex_size == ARRAY_SIZE(sna->render.vertex_data));
  224.     }
  225.  
  226.     if (free_bo)
  227.         kgem_bo_destroy(&sna->kgem, free_bo);
  228. }
  229.  
  230. /* specialised vertex emission routines */
  231.  
  232. #define OUT_VERTEX(x,y) vertex_emit_2s(sna, x,y) /* XXX assert(!too_large(x, y)); */
  233. #define OUT_VERTEX_F(v) vertex_emit(sna, v)
  234.  
  235. force_inline static float
  236. compute_linear(const struct sna_composite_channel *channel,
  237.                int16_t x, int16_t y)
  238. {
  239.         return ((x+channel->offset[0]) * channel->u.linear.dx +
  240.                 (y+channel->offset[1]) * channel->u.linear.dy +
  241.                 channel->u.linear.offset);
  242. }
  243.  
  244. sse2 inline static void
  245. emit_texcoord(struct sna *sna,
  246.               const struct sna_composite_channel *channel,
  247.               int16_t x, int16_t y)
  248. {
  249.         if (channel->is_solid) {
  250.                 OUT_VERTEX_F(x);
  251.                 return;
  252.         }
  253.  
  254.         x += channel->offset[0];
  255.         y += channel->offset[1];
  256.  
  257.         if (channel->is_affine) {
  258.                 float s, t;
  259.  
  260.                 sna_get_transformed_coordinates(x, y,
  261.                                                 channel->transform,
  262.                                                 &s, &t);
  263.                 OUT_VERTEX_F(s * channel->scale[0]);
  264.                 OUT_VERTEX_F(t * channel->scale[1]);
  265.         } else {
  266.                 float s, t, w;
  267.  
  268.                 sna_get_transformed_coordinates_3d(x, y,
  269.                                                    channel->transform,
  270.                                                    &s, &t, &w);
  271.                 OUT_VERTEX_F(s * channel->scale[0]);
  272.                 OUT_VERTEX_F(t * channel->scale[1]);
  273.                 OUT_VERTEX_F(w);
  274.         }
  275. }
  276.  
  277. sse2 force_inline static void
  278. emit_vertex(struct sna *sna,
  279.             const struct sna_composite_op *op,
  280.             int16_t srcX, int16_t srcY,
  281.             int16_t mskX, int16_t mskY,
  282.             int16_t dstX, int16_t dstY)
  283. {
  284.         OUT_VERTEX(dstX, dstY);
  285.         emit_texcoord(sna, &op->src, srcX, srcY);
  286. }
  287.  
  288. sse2 fastcall static void
  289. emit_primitive(struct sna *sna,
  290.                const struct sna_composite_op *op,
  291.                const struct sna_composite_rectangles *r)
  292. {
  293.         emit_vertex(sna, op,
  294.                     r->src.x + r->width,  r->src.y + r->height,
  295.                     r->mask.x + r->width, r->mask.y + r->height,
  296.                     r->dst.x + r->width, r->dst.y + r->height);
  297.         emit_vertex(sna, op,
  298.                     r->src.x,  r->src.y + r->height,
  299.                     r->mask.x, r->mask.y + r->height,
  300.                     r->dst.x,  r->dst.y + r->height);
  301.         emit_vertex(sna, op,
  302.                     r->src.x,  r->src.y,
  303.                     r->mask.x, r->mask.y,
  304.                     r->dst.x,  r->dst.y);
  305. }
  306.  
  307. sse2 force_inline static void
  308. emit_vertex_mask(struct sna *sna,
  309.                  const struct sna_composite_op *op,
  310.                  int16_t srcX, int16_t srcY,
  311.                  int16_t mskX, int16_t mskY,
  312.                  int16_t dstX, int16_t dstY)
  313. {
  314.         OUT_VERTEX(dstX, dstY);
  315.         emit_texcoord(sna, &op->src, srcX, srcY);
  316.         emit_texcoord(sna, &op->mask, mskX, mskY);
  317. }
  318.  
  319. sse2 fastcall static void
  320. emit_primitive_mask(struct sna *sna,
  321.                     const struct sna_composite_op *op,
  322.                     const struct sna_composite_rectangles *r)
  323. {
  324.         emit_vertex_mask(sna, op,
  325.                          r->src.x + r->width,  r->src.y + r->height,
  326.                          r->mask.x + r->width, r->mask.y + r->height,
  327.                          r->dst.x + r->width, r->dst.y + r->height);
  328.         emit_vertex_mask(sna, op,
  329.                          r->src.x,  r->src.y + r->height,
  330.                          r->mask.x, r->mask.y + r->height,
  331.                          r->dst.x,  r->dst.y + r->height);
  332.         emit_vertex_mask(sna, op,
  333.                          r->src.x,  r->src.y,
  334.                          r->mask.x, r->mask.y,
  335.                          r->dst.x,  r->dst.y);
  336. }
  337.  
  338. sse2 fastcall static void
  339. emit_primitive_solid(struct sna *sna,
  340.                      const struct sna_composite_op *op,
  341.                      const struct sna_composite_rectangles *r)
  342. {
  343.         float *v;
  344.         union {
  345.                 struct sna_coordinate p;
  346.                 float f;
  347.         } dst;
  348.  
  349.         assert(op->floats_per_rect == 6);
  350.         assert((sna->render.vertex_used % 2) == 0);
  351.         v = sna->render.vertices + sna->render.vertex_used;
  352.         sna->render.vertex_used += 6;
  353.         assert(sna->render.vertex_used <= sna->render.vertex_size);
  354.  
  355.         dst.p.x = r->dst.x + r->width;
  356.         dst.p.y = r->dst.y + r->height;
  357.         v[0] = dst.f;
  358.         dst.p.x = r->dst.x;
  359.         v[2] = dst.f;
  360.         dst.p.y = r->dst.y;
  361.         v[4] = dst.f;
  362.  
  363.         v[5] = v[3] = v[1] = .5;
  364. }
  365.  
  366. sse2 fastcall static void
  367. emit_boxes_solid(const struct sna_composite_op *op,
  368.                  const BoxRec *box, int nbox,
  369.                  float *v)
  370. {
  371.         do {
  372.                 union {
  373.                         struct sna_coordinate p;
  374.                         float f;
  375.                 } dst;
  376.  
  377.                 dst.p.x = box->x2;
  378.                 dst.p.y = box->y2;
  379.                 v[0] = dst.f;
  380.                 dst.p.x = box->x1;
  381.                 v[2] = dst.f;
  382.                 dst.p.y = box->y1;
  383.                 v[4] = dst.f;
  384.  
  385.                 v[5] = v[3] = v[1] = .5;
  386.                 box++;
  387.                 v += 6;
  388.         } while (--nbox);
  389. }
  390.  
  391. sse2 fastcall static void
  392. emit_primitive_linear(struct sna *sna,
  393.                       const struct sna_composite_op *op,
  394.                       const struct sna_composite_rectangles *r)
  395. {
  396.         float *v;
  397.         union {
  398.                 struct sna_coordinate p;
  399.                 float f;
  400.         } dst;
  401.  
  402.         assert(op->floats_per_rect == 6);
  403.         assert((sna->render.vertex_used % 2) == 0);
  404.         v = sna->render.vertices + sna->render.vertex_used;
  405.         sna->render.vertex_used += 6;
  406.         assert(sna->render.vertex_used <= sna->render.vertex_size);
  407.  
  408.         dst.p.x = r->dst.x + r->width;
  409.         dst.p.y = r->dst.y + r->height;
  410.         v[0] = dst.f;
  411.         dst.p.x = r->dst.x;
  412.         v[2] = dst.f;
  413.         dst.p.y = r->dst.y;
  414.         v[4] = dst.f;
  415.  
  416.         v[1] = compute_linear(&op->src, r->src.x+r->width, r->src.y+r->height);
  417.         v[3] = compute_linear(&op->src, r->src.x, r->src.y+r->height);
  418.         v[5] = compute_linear(&op->src, r->src.x, r->src.y);
  419. }
  420.  
  421. sse2 fastcall static void
  422. emit_boxes_linear(const struct sna_composite_op *op,
  423.                   const BoxRec *box, int nbox,
  424.                   float *v)
  425. {
  426.         union {
  427.                 struct sna_coordinate p;
  428.                 float f;
  429.         } dst;
  430.  
  431.         do {
  432.                 dst.p.x = box->x2;
  433.                 dst.p.y = box->y2;
  434.                 v[0] = dst.f;
  435.                 dst.p.x = box->x1;
  436.                 v[2] = dst.f;
  437.                 dst.p.y = box->y1;
  438.                 v[4] = dst.f;
  439.  
  440.                 v[1] = compute_linear(&op->src, box->x2, box->y2);
  441.                 v[3] = compute_linear(&op->src, box->x1, box->y2);
  442.                 v[5] = compute_linear(&op->src, box->x1, box->y1);
  443.  
  444.                 v += 6;
  445.                 box++;
  446.         } while (--nbox);
  447. }
  448.  
  449. sse2 fastcall static void
  450. emit_primitive_identity_source(struct sna *sna,
  451.                                const struct sna_composite_op *op,
  452.                                const struct sna_composite_rectangles *r)
  453. {
  454.         union {
  455.                 struct sna_coordinate p;
  456.                 float f;
  457.         } dst;
  458.         float *v;
  459.  
  460.         assert(op->floats_per_rect == 9);
  461.         assert((sna->render.vertex_used % 3) == 0);
  462.         v = sna->render.vertices + sna->render.vertex_used;
  463.         sna->render.vertex_used += 9;
  464.  
  465.         dst.p.x = r->dst.x + r->width;
  466.         dst.p.y = r->dst.y + r->height;
  467.         v[0] = dst.f;
  468.         dst.p.x = r->dst.x;
  469.         v[3] = dst.f;
  470.         dst.p.y = r->dst.y;
  471.         v[6] = dst.f;
  472.  
  473.         v[7] = v[4] = (r->src.x + op->src.offset[0]) * op->src.scale[0];
  474.         v[1] = v[4] + r->width * op->src.scale[0];
  475.  
  476.         v[8] = (r->src.y + op->src.offset[1]) * op->src.scale[1];
  477.         v[5] = v[2] = v[8] + r->height * op->src.scale[1];
  478. }
  479.  
  480. sse2 fastcall static void
  481. emit_boxes_identity_source(const struct sna_composite_op *op,
  482.                            const BoxRec *box, int nbox,
  483.                            float *v)
  484. {
  485.         do {
  486.                 union {
  487.                         struct sna_coordinate p;
  488.                         float f;
  489.                 } dst;
  490.  
  491.                 dst.p.x = box->x2;
  492.                 dst.p.y = box->y2;
  493.                 v[0] = dst.f;
  494.                 dst.p.x = box->x1;
  495.                 v[3] = dst.f;
  496.                 dst.p.y = box->y1;
  497.                 v[6] = dst.f;
  498.  
  499.                 v[7] = v[4] = (box->x1 + op->src.offset[0]) * op->src.scale[0];
  500.                 v[1] = (box->x2 + op->src.offset[0]) * op->src.scale[0];
  501.  
  502.                 v[8] = (box->y1 + op->src.offset[1]) * op->src.scale[1];
  503.                 v[2] = v[5] = (box->y2 + op->src.offset[1]) * op->src.scale[1];
  504.  
  505.                 v += 9;
  506.                 box++;
  507.         } while (--nbox);
  508. }
  509.  
  510. sse2 fastcall static void
  511. emit_primitive_simple_source(struct sna *sna,
  512.                              const struct sna_composite_op *op,
  513.                              const struct sna_composite_rectangles *r)
  514. {
  515.         float *v;
  516.         union {
  517.                 struct sna_coordinate p;
  518.                 float f;
  519.         } dst;
  520.  
  521.         float xx = op->src.transform->matrix[0][0];
  522.         float x0 = op->src.transform->matrix[0][2];
  523.         float yy = op->src.transform->matrix[1][1];
  524.         float y0 = op->src.transform->matrix[1][2];
  525.         float sx = op->src.scale[0];
  526.         float sy = op->src.scale[1];
  527.         int16_t tx = op->src.offset[0];
  528.         int16_t ty = op->src.offset[1];
  529.  
  530.         assert(op->floats_per_rect == 9);
  531.         assert((sna->render.vertex_used % 3) == 0);
  532.         v = sna->render.vertices + sna->render.vertex_used;
  533.         sna->render.vertex_used += 3*3;
  534.  
  535.         dst.p.x = r->dst.x + r->width;
  536.         dst.p.y = r->dst.y + r->height;
  537.         v[0] = dst.f;
  538.         v[1] = ((r->src.x + r->width + tx) * xx + x0) * sx;
  539.         v[5] = v[2] = ((r->src.y + r->height + ty) * yy + y0) * sy;
  540.  
  541.         dst.p.x = r->dst.x;
  542.         v[3] = dst.f;
  543.         v[7] = v[4] = ((r->src.x + tx) * xx + x0) * sx;
  544.  
  545.         dst.p.y = r->dst.y;
  546.         v[6] = dst.f;
  547.         v[8] = ((r->src.y + ty) * yy + y0) * sy;
  548. }
  549.  
  550. sse2 fastcall static void
  551. emit_boxes_simple_source(const struct sna_composite_op *op,
  552.                          const BoxRec *box, int nbox,
  553.                          float *v)
  554. {
  555.         float xx = op->src.transform->matrix[0][0];
  556.         float x0 = op->src.transform->matrix[0][2];
  557.         float yy = op->src.transform->matrix[1][1];
  558.         float y0 = op->src.transform->matrix[1][2];
  559.         float sx = op->src.scale[0];
  560.         float sy = op->src.scale[1];
  561.         int16_t tx = op->src.offset[0];
  562.         int16_t ty = op->src.offset[1];
  563.  
  564.         do {
  565.                 union {
  566.                         struct sna_coordinate p;
  567.                         float f;
  568.                 } dst;
  569.  
  570.                 dst.p.x = box->x2;
  571.                 dst.p.y = box->y2;
  572.                 v[0] = dst.f;
  573.                 v[1] = ((box->x2 + tx) * xx + x0) * sx;
  574.                 v[5] = v[2] = ((box->y2 + ty) * yy + y0) * sy;
  575.  
  576.                 dst.p.x = box->x1;
  577.                 v[3] = dst.f;
  578.                 v[7] = v[4] = ((box->x1 + tx) * xx + x0) * sx;
  579.  
  580.                 dst.p.y = box->y1;
  581.                 v[6] = dst.f;
  582.                 v[8] = ((box->y1 + ty) * yy + y0) * sy;
  583.  
  584.                 v += 9;
  585.                 box++;
  586.         } while (--nbox);
  587. }
  588.  
  589. sse2 fastcall static void
  590. emit_primitive_affine_source(struct sna *sna,
  591.                              const struct sna_composite_op *op,
  592.                              const struct sna_composite_rectangles *r)
  593. {
  594.         union {
  595.                 struct sna_coordinate p;
  596.                 float f;
  597.         } dst;
  598.         float *v;
  599.  
  600.         assert(op->floats_per_rect == 9);
  601.         assert((sna->render.vertex_used % 3) == 0);
  602.         v = sna->render.vertices + sna->render.vertex_used;
  603.         sna->render.vertex_used += 9;
  604.  
  605.         dst.p.x = r->dst.x + r->width;
  606.         dst.p.y = r->dst.y + r->height;
  607.         v[0] = dst.f;
  608.         _sna_get_transformed_scaled(op->src.offset[0] + r->src.x + r->width,
  609.                                     op->src.offset[1] + r->src.y + r->height,
  610.                                     op->src.transform, op->src.scale,
  611.                                     &v[1], &v[2]);
  612.  
  613.         dst.p.x = r->dst.x;
  614.         v[3] = dst.f;
  615.         _sna_get_transformed_scaled(op->src.offset[0] + r->src.x,
  616.                                     op->src.offset[1] + r->src.y + r->height,
  617.                                     op->src.transform, op->src.scale,
  618.                                     &v[4], &v[5]);
  619.  
  620.         dst.p.y = r->dst.y;
  621.         v[6] = dst.f;
  622.         _sna_get_transformed_scaled(op->src.offset[0] + r->src.x,
  623.                                     op->src.offset[1] + r->src.y,
  624.                                     op->src.transform, op->src.scale,
  625.                                     &v[7], &v[8]);
  626. }
  627.  
  628. sse2 fastcall static void
  629. emit_boxes_affine_source(const struct sna_composite_op *op,
  630.                          const BoxRec *box, int nbox,
  631.                          float *v)
  632. {
  633.         do {
  634.                 union {
  635.                         struct sna_coordinate p;
  636.                         float f;
  637.                 } dst;
  638.  
  639.                 dst.p.x = box->x2;
  640.                 dst.p.y = box->y2;
  641.                 v[0] = dst.f;
  642.                 _sna_get_transformed_scaled(op->src.offset[0] + box->x2,
  643.                                             op->src.offset[1] + box->y2,
  644.                                             op->src.transform, op->src.scale,
  645.                                             &v[1], &v[2]);
  646.  
  647.                 dst.p.x = box->x1;
  648.                 v[3] = dst.f;
  649.                 _sna_get_transformed_scaled(op->src.offset[0] + box->x1,
  650.                                             op->src.offset[1] + box->y2,
  651.                                             op->src.transform, op->src.scale,
  652.                                             &v[4], &v[5]);
  653.  
  654.                 dst.p.y = box->y1;
  655.                 v[6] = dst.f;
  656.                 _sna_get_transformed_scaled(op->src.offset[0] + box->x1,
  657.                                             op->src.offset[1] + box->y1,
  658.                                             op->src.transform, op->src.scale,
  659.                                             &v[7], &v[8]);
  660.                 box++;
  661.                 v += 9;
  662.         } while (--nbox);
  663. }
  664.  
  665. sse2 fastcall static void
  666. emit_primitive_identity_mask(struct sna *sna,
  667.                              const struct sna_composite_op *op,
  668.                              const struct sna_composite_rectangles *r)
  669. {
  670.         union {
  671.                 struct sna_coordinate p;
  672.                 float f;
  673.         } dst;
  674.         float msk_x, msk_y;
  675.         float w, h;
  676.         float *v;
  677.  
  678.         msk_x = r->mask.x + op->mask.offset[0];
  679.         msk_y = r->mask.y + op->mask.offset[1];
  680.         w = r->width;
  681.         h = r->height;
  682.  
  683.         DBG(("%s: dst=(%d, %d), mask=(%f, %f) x (%f, %f)\n",
  684.              __FUNCTION__, r->dst.x, r->dst.y, msk_x, msk_y, w, h));
  685.  
  686.         assert(op->floats_per_rect == 12);
  687.         assert((sna->render.vertex_used % 4) == 0);
  688.         v = sna->render.vertices + sna->render.vertex_used;
  689.         sna->render.vertex_used += 12;
  690.  
  691.         dst.p.x = r->dst.x + r->width;
  692.         dst.p.y = r->dst.y + r->height;
  693.         v[0] = dst.f;
  694.         v[2] = (msk_x + w) * op->mask.scale[0];
  695.         v[7] = v[3] = (msk_y + h) * op->mask.scale[1];
  696.  
  697.         dst.p.x = r->dst.x;
  698.         v[4] = dst.f;
  699.         v[10] = v[6] = msk_x * op->mask.scale[0];
  700.  
  701.         dst.p.y = r->dst.y;
  702.         v[8] = dst.f;
  703.         v[11] = msk_y * op->mask.scale[1];
  704.  
  705.         v[9] = v[5] = v[1] = .5;
  706. }
  707.  
  708. sse2 fastcall static void
  709. emit_boxes_identity_mask(const struct sna_composite_op *op,
  710.                          const BoxRec *box, int nbox,
  711.                          float *v)
  712. {
  713.         float msk_x = op->mask.offset[0];
  714.         float msk_y = op->mask.offset[1];
  715.  
  716.         do {
  717.                 union {
  718.                         struct sna_coordinate p;
  719.                         float f;
  720.                 } dst;
  721.  
  722.                 dst.p.x = box->x2;
  723.                 dst.p.y = box->y2;
  724.                 v[0] = dst.f;
  725.                 v[2] = (msk_x + box->x2) * op->mask.scale[0];
  726.                 v[7] = v[3] = (msk_y + box->y2) * op->mask.scale[1];
  727.  
  728.                 dst.p.x = box->x1;
  729.                 v[4] = dst.f;
  730.                 v[10] = v[6] = (msk_x + box->x1) * op->mask.scale[0];
  731.  
  732.                 dst.p.y = box->y1;
  733.                 v[8] = dst.f;
  734.                 v[11] = (msk_y + box->y1) * op->mask.scale[1];
  735.  
  736.                 v[9] = v[5] = v[1] = .5;
  737.                 v += 12;
  738.                 box++;
  739.         } while (--nbox);
  740. }
  741.  
  742. sse2 fastcall static void
  743. emit_primitive_linear_identity_mask(struct sna *sna,
  744.                                     const struct sna_composite_op *op,
  745.                                     const struct sna_composite_rectangles *r)
  746. {
  747.         union {
  748.                 struct sna_coordinate p;
  749.                 float f;
  750.         } dst;
  751.         float msk_x, msk_y;
  752.         float w, h;
  753.         float *v;
  754.  
  755.         msk_x = r->mask.x + op->mask.offset[0];
  756.         msk_y = r->mask.y + op->mask.offset[1];
  757.         w = r->width;
  758.         h = r->height;
  759.  
  760.         DBG(("%s: dst=(%d, %d), mask=(%f, %f) x (%f, %f)\n",
  761.              __FUNCTION__, r->dst.x, r->dst.y, msk_x, msk_y, w, h));
  762.  
  763.         assert(op->floats_per_rect == 12);
  764.         assert((sna->render.vertex_used % 4) == 0);
  765.         v = sna->render.vertices + sna->render.vertex_used;
  766.         sna->render.vertex_used += 12;
  767.  
  768.         dst.p.x = r->dst.x + r->width;
  769.         dst.p.y = r->dst.y + r->height;
  770.         v[0] = dst.f;
  771.         v[2] = (msk_x + w) * op->mask.scale[0];
  772.         v[7] = v[3] = (msk_y + h) * op->mask.scale[1];
  773.  
  774.         dst.p.x = r->dst.x;
  775.         v[4] = dst.f;
  776.         v[10] = v[6] = msk_x * op->mask.scale[0];
  777.  
  778.         dst.p.y = r->dst.y;
  779.         v[8] = dst.f;
  780.         v[11] = msk_y * op->mask.scale[1];
  781.  
  782.         v[1] = compute_linear(&op->src, r->src.x+r->width, r->src.y+r->height);
  783.         v[5] = compute_linear(&op->src, r->src.x, r->src.y+r->height);
  784.         v[9] = compute_linear(&op->src, r->src.x, r->src.y);
  785. }
  786.  
  787. sse2 fastcall static void
  788. emit_boxes_linear_identity_mask(const struct sna_composite_op *op,
  789.                                 const BoxRec *box, int nbox,
  790.                                 float *v)
  791. {
  792.         float msk_x = op->mask.offset[0];
  793.         float msk_y = op->mask.offset[1];
  794.  
  795.         do {
  796.                 union {
  797.                         struct sna_coordinate p;
  798.                         float f;
  799.                 } dst;
  800.  
  801.                 dst.p.x = box->x2;
  802.                 dst.p.y = box->y2;
  803.                 v[0] = dst.f;
  804.                 v[2] = (msk_x + box->x2) * op->mask.scale[0];
  805.                 v[7] = v[3] = (msk_y + box->y2) * op->mask.scale[1];
  806.  
  807.                 dst.p.x = box->x1;
  808.                 v[4] = dst.f;
  809.                 v[10] = v[6] = (msk_x + box->x1) * op->mask.scale[0];
  810.  
  811.                 dst.p.y = box->y1;
  812.                 v[8] = dst.f;
  813.                 v[11] = (msk_y + box->y1) * op->mask.scale[1];
  814.  
  815.                 v[1] = compute_linear(&op->src, box->x2, box->y2);
  816.                 v[5] = compute_linear(&op->src, box->x1, box->y2);
  817.                 v[9] = compute_linear(&op->src, box->x1, box->y1);
  818.  
  819.                 v += 12;
  820.                 box++;
  821.         } while (--nbox);
  822. }
  823.  
  824. sse2 fastcall static void
  825. emit_primitive_identity_source_mask(struct sna *sna,
  826.                                     const struct sna_composite_op *op,
  827.                                     const struct sna_composite_rectangles *r)
  828. {
  829.         union {
  830.                 struct sna_coordinate p;
  831.                 float f;
  832.         } dst;
  833.         float src_x, src_y;
  834.         float msk_x, msk_y;
  835.         float w, h;
  836.         float *v;
  837.  
  838.         src_x = r->src.x + op->src.offset[0];
  839.         src_y = r->src.y + op->src.offset[1];
  840.         msk_x = r->mask.x + op->mask.offset[0];
  841.         msk_y = r->mask.y + op->mask.offset[1];
  842.         w = r->width;
  843.         h = r->height;
  844.  
  845.         assert(op->floats_per_rect == 15);
  846.         assert((sna->render.vertex_used % 5) == 0);
  847.         v = sna->render.vertices + sna->render.vertex_used;
  848.         sna->render.vertex_used += 15;
  849.  
  850.         dst.p.x = r->dst.x + r->width;
  851.         dst.p.y = r->dst.y + r->height;
  852.         v[0] = dst.f;
  853.         v[1] = (src_x + w) * op->src.scale[0];
  854.         v[2] = (src_y + h) * op->src.scale[1];
  855.         v[3] = (msk_x + w) * op->mask.scale[0];
  856.         v[4] = (msk_y + h) * op->mask.scale[1];
  857.  
  858.         dst.p.x = r->dst.x;
  859.         v[5] = dst.f;
  860.         v[6] = src_x * op->src.scale[0];
  861.         v[7] = v[2];
  862.         v[8] = msk_x * op->mask.scale[0];
  863.         v[9] = v[4];
  864.  
  865.         dst.p.y = r->dst.y;
  866.         v[10] = dst.f;
  867.         v[11] = v[6];
  868.         v[12] = src_y * op->src.scale[1];
  869.         v[13] = v[8];
  870.         v[14] = msk_y * op->mask.scale[1];
  871. }
  872.  
  873. sse2 fastcall static void
  874. emit_primitive_simple_source_identity(struct sna *sna,
  875.                                       const struct sna_composite_op *op,
  876.                                       const struct sna_composite_rectangles *r)
  877. {
  878.         float *v;
  879.         union {
  880.                 struct sna_coordinate p;
  881.                 float f;
  882.         } dst;
  883.  
  884.         float xx = op->src.transform->matrix[0][0];
  885.         float x0 = op->src.transform->matrix[0][2];
  886.         float yy = op->src.transform->matrix[1][1];
  887.         float y0 = op->src.transform->matrix[1][2];
  888.         float sx = op->src.scale[0];
  889.         float sy = op->src.scale[1];
  890.         int16_t tx = op->src.offset[0];
  891.         int16_t ty = op->src.offset[1];
  892.         float msk_x = r->mask.x + op->mask.offset[0];
  893.         float msk_y = r->mask.y + op->mask.offset[1];
  894.         float w = r->width, h = r->height;
  895.  
  896.         assert(op->floats_per_rect == 15);
  897.         assert((sna->render.vertex_used % 5) == 0);
  898.         v = sna->render.vertices + sna->render.vertex_used;
  899.         sna->render.vertex_used += 3*5;
  900.  
  901.         dst.p.x = r->dst.x + r->width;
  902.         dst.p.y = r->dst.y + r->height;
  903.         v[0] = dst.f;
  904.         v[1] = ((r->src.x + r->width + tx) * xx + x0) * sx;
  905.         v[2] = ((r->src.y + r->height + ty) * yy + y0) * sy;
  906.         v[3] = (msk_x + w) * op->mask.scale[0];
  907.         v[4] = (msk_y + h) * op->mask.scale[1];
  908.  
  909.         dst.p.x = r->dst.x;
  910.         v[5] = dst.f;
  911.         v[6] = ((r->src.x + tx) * xx + x0) * sx;
  912.         v[7] = v[2];
  913.         v[8] = msk_x * op->mask.scale[0];
  914.         v[9] = v[4];
  915.  
  916.         dst.p.y = r->dst.y;
  917.         v[10] = dst.f;
  918.         v[11] = v[6];
  919.         v[12] = ((r->src.y + ty) * yy + y0) * sy;
  920.         v[13] = v[8];
  921.         v[14] = msk_y * op->mask.scale[1];
  922. }
  923.  
  924. sse2 fastcall static void
  925. emit_primitive_affine_source_identity(struct sna *sna,
  926.                                       const struct sna_composite_op *op,
  927.                                       const struct sna_composite_rectangles *r)
  928. {
  929.         float *v;
  930.         union {
  931.                 struct sna_coordinate p;
  932.                 float f;
  933.         } dst;
  934.         float msk_x = r->mask.x + op->mask.offset[0];
  935.         float msk_y = r->mask.y + op->mask.offset[1];
  936.         float w = r->width, h = r->height;
  937.  
  938.         assert(op->floats_per_rect == 15);
  939.         assert((sna->render.vertex_used % 5) == 0);
  940.         v = sna->render.vertices + sna->render.vertex_used;
  941.         sna->render.vertex_used += 3*5;
  942.  
  943.         dst.p.x = r->dst.x + r->width;
  944.         dst.p.y = r->dst.y + r->height;
  945.         v[0] = dst.f;
  946.         _sna_get_transformed_scaled(op->src.offset[0] + r->src.x + r->width,
  947.                                     op->src.offset[1] + r->src.y + r->height,
  948.                                     op->src.transform, op->src.scale,
  949.                                     &v[1], &v[2]);
  950.         v[3] = (msk_x + w) * op->mask.scale[0];
  951.         v[4] = (msk_y + h) * op->mask.scale[1];
  952.  
  953.         dst.p.x = r->dst.x;
  954.         v[5] = dst.f;
  955.         _sna_get_transformed_scaled(op->src.offset[0] + r->src.x,
  956.                                     op->src.offset[1] + r->src.y + r->height,
  957.                                     op->src.transform, op->src.scale,
  958.                                     &v[6], &v[7]);
  959.         v[8] = msk_x * op->mask.scale[0];
  960.         v[9] = v[4];
  961.  
  962.         dst.p.y = r->dst.y;
  963.         v[10] = dst.f;
  964.         _sna_get_transformed_scaled(op->src.offset[0] + r->src.x,
  965.                                     op->src.offset[1] + r->src.y,
  966.                                     op->src.transform, op->src.scale,
  967.                                     &v[11], &v[12]);
  968.         v[13] = v[8];
  969.         v[14] = msk_y * op->mask.scale[1];
  970. }
  971.  
  972. /* SSE4_2 */
  973. #if defined(sse4_2)
  974.  
  975. sse4_2 fastcall static void
  976. emit_primitive_linear__sse4_2(struct sna *sna,
  977.                               const struct sna_composite_op *op,
  978.                               const struct sna_composite_rectangles *r)
  979. {
  980.         float *v;
  981.         union {
  982.                 struct sna_coordinate p;
  983.                 float f;
  984.         } dst;
  985.  
  986.         assert(op->floats_per_rect == 6);
  987.         assert((sna->render.vertex_used % 2) == 0);
  988.         v = sna->render.vertices + sna->render.vertex_used;
  989.         sna->render.vertex_used += 6;
  990.         assert(sna->render.vertex_used <= sna->render.vertex_size);
  991.  
  992.         dst.p.x = r->dst.x + r->width;
  993.         dst.p.y = r->dst.y + r->height;
  994.         v[0] = dst.f;
  995.         dst.p.x = r->dst.x;
  996.         v[2] = dst.f;
  997.         dst.p.y = r->dst.y;
  998.         v[4] = dst.f;
  999.  
  1000.         v[1] = compute_linear(&op->src, r->src.x+r->width, r->src.y+r->height);
  1001.         v[3] = compute_linear(&op->src, r->src.x, r->src.y+r->height);
  1002.         v[5] = compute_linear(&op->src, r->src.x, r->src.y);
  1003. }
  1004.  
  1005. sse4_2 fastcall static void
  1006. emit_boxes_linear__sse4_2(const struct sna_composite_op *op,
  1007.                           const BoxRec *box, int nbox,
  1008.                           float *v)
  1009. {
  1010.         union {
  1011.                 struct sna_coordinate p;
  1012.                 float f;
  1013.         } dst;
  1014.  
  1015.         do {
  1016.                 dst.p.x = box->x2;
  1017.                 dst.p.y = box->y2;
  1018.                 v[0] = dst.f;
  1019.                 dst.p.x = box->x1;
  1020.                 v[2] = dst.f;
  1021.                 dst.p.y = box->y1;
  1022.                 v[4] = dst.f;
  1023.  
  1024.                 v[1] = compute_linear(&op->src, box->x2, box->y2);
  1025.                 v[3] = compute_linear(&op->src, box->x1, box->y2);
  1026.                 v[5] = compute_linear(&op->src, box->x1, box->y1);
  1027.  
  1028.                 v += 6;
  1029.                 box++;
  1030.         } while (--nbox);
  1031. }
  1032.  
  1033. sse4_2 fastcall static void
  1034. emit_primitive_identity_source__sse4_2(struct sna *sna,
  1035.                                        const struct sna_composite_op *op,
  1036.                                        const struct sna_composite_rectangles *r)
  1037. {
  1038.         union {
  1039.                 struct sna_coordinate p;
  1040.                 float f;
  1041.         } dst;
  1042.         float *v;
  1043.  
  1044.         assert(op->floats_per_rect == 9);
  1045.         assert((sna->render.vertex_used % 3) == 0);
  1046.         v = sna->render.vertices + sna->render.vertex_used;
  1047.         sna->render.vertex_used += 9;
  1048.  
  1049.         dst.p.x = r->dst.x + r->width;
  1050.         dst.p.y = r->dst.y + r->height;
  1051.         v[0] = dst.f;
  1052.         dst.p.x = r->dst.x;
  1053.         v[3] = dst.f;
  1054.         dst.p.y = r->dst.y;
  1055.         v[6] = dst.f;
  1056.  
  1057.         v[7] = v[4] = (r->src.x + op->src.offset[0]) * op->src.scale[0];
  1058.         v[1] = v[4] + r->width * op->src.scale[0];
  1059.  
  1060.         v[8] = (r->src.y + op->src.offset[1]) * op->src.scale[1];
  1061.         v[5] = v[2] = v[8] + r->height * op->src.scale[1];
  1062. }
  1063.  
  1064. sse4_2 fastcall static void
  1065. emit_boxes_identity_source__sse4_2(const struct sna_composite_op *op,
  1066.                                    const BoxRec *box, int nbox,
  1067.                                    float *v)
  1068. {
  1069.         do {
  1070.                 union {
  1071.                         struct sna_coordinate p;
  1072.                         float f;
  1073.                 } dst;
  1074.  
  1075.                 dst.p.x = box->x2;
  1076.                 dst.p.y = box->y2;
  1077.                 v[0] = dst.f;
  1078.                 dst.p.x = box->x1;
  1079.                 v[3] = dst.f;
  1080.                 dst.p.y = box->y1;
  1081.                 v[6] = dst.f;
  1082.  
  1083.                 v[7] = v[4] = (box->x1 + op->src.offset[0]) * op->src.scale[0];
  1084.                 v[1] = (box->x2 + op->src.offset[0]) * op->src.scale[0];
  1085.  
  1086.                 v[8] = (box->y1 + op->src.offset[1]) * op->src.scale[1];
  1087.                 v[2] = v[5] = (box->y2 + op->src.offset[1]) * op->src.scale[1];
  1088.  
  1089.                 v += 9;
  1090.                 box++;
  1091.         } while (--nbox);
  1092. }
  1093.  
  1094. sse4_2 fastcall static void
  1095. emit_primitive_simple_source__sse4_2(struct sna *sna,
  1096.                                      const struct sna_composite_op *op,
  1097.                                      const struct sna_composite_rectangles *r)
  1098. {
  1099.         float *v;
  1100.         union {
  1101.                 struct sna_coordinate p;
  1102.                 float f;
  1103.         } dst;
  1104.  
  1105.         float xx = op->src.transform->matrix[0][0];
  1106.         float x0 = op->src.transform->matrix[0][2];
  1107.         float yy = op->src.transform->matrix[1][1];
  1108.         float y0 = op->src.transform->matrix[1][2];
  1109.         float sx = op->src.scale[0];
  1110.         float sy = op->src.scale[1];
  1111.         int16_t tx = op->src.offset[0];
  1112.         int16_t ty = op->src.offset[1];
  1113.  
  1114.         assert(op->floats_per_rect == 9);
  1115.         assert((sna->render.vertex_used % 3) == 0);
  1116.         v = sna->render.vertices + sna->render.vertex_used;
  1117.         sna->render.vertex_used += 3*3;
  1118.  
  1119.         dst.p.x = r->dst.x + r->width;
  1120.         dst.p.y = r->dst.y + r->height;
  1121.         v[0] = dst.f;
  1122.         v[1] = ((r->src.x + r->width + tx) * xx + x0) * sx;
  1123.         v[5] = v[2] = ((r->src.y + r->height + ty) * yy + y0) * sy;
  1124.  
  1125.         dst.p.x = r->dst.x;
  1126.         v[3] = dst.f;
  1127.         v[7] = v[4] = ((r->src.x + tx) * xx + x0) * sx;
  1128.  
  1129.         dst.p.y = r->dst.y;
  1130.         v[6] = dst.f;
  1131.         v[8] = ((r->src.y + ty) * yy + y0) * sy;
  1132. }
  1133.  
  1134. sse4_2 fastcall static void
  1135. emit_boxes_simple_source__sse4_2(const struct sna_composite_op *op,
  1136.                                  const BoxRec *box, int nbox,
  1137.                                  float *v)
  1138. {
  1139.         float xx = op->src.transform->matrix[0][0];
  1140.         float x0 = op->src.transform->matrix[0][2];
  1141.         float yy = op->src.transform->matrix[1][1];
  1142.         float y0 = op->src.transform->matrix[1][2];
  1143.         float sx = op->src.scale[0];
  1144.         float sy = op->src.scale[1];
  1145.         int16_t tx = op->src.offset[0];
  1146.         int16_t ty = op->src.offset[1];
  1147.  
  1148.         do {
  1149.                 union {
  1150.                         struct sna_coordinate p;
  1151.                         float f;
  1152.                 } dst;
  1153.  
  1154.                 dst.p.x = box->x2;
  1155.                 dst.p.y = box->y2;
  1156.                 v[0] = dst.f;
  1157.                 v[1] = ((box->x2 + tx) * xx + x0) * sx;
  1158.                 v[5] = v[2] = ((box->y2 + ty) * yy + y0) * sy;
  1159.  
  1160.                 dst.p.x = box->x1;
  1161.                 v[3] = dst.f;
  1162.                 v[7] = v[4] = ((box->x1 + tx) * xx + x0) * sx;
  1163.  
  1164.                 dst.p.y = box->y1;
  1165.                 v[6] = dst.f;
  1166.                 v[8] = ((box->y1 + ty) * yy + y0) * sy;
  1167.  
  1168.                 v += 9;
  1169.                 box++;
  1170.         } while (--nbox);
  1171. }
  1172.  
  1173. sse4_2 fastcall static void
  1174. emit_primitive_identity_mask__sse4_2(struct sna *sna,
  1175.                                      const struct sna_composite_op *op,
  1176.                                      const struct sna_composite_rectangles *r)
  1177. {
  1178.         union {
  1179.                 struct sna_coordinate p;
  1180.                 float f;
  1181.         } dst;
  1182.         float msk_x, msk_y;
  1183.         float w, h;
  1184.         float *v;
  1185.  
  1186.         msk_x = r->mask.x + op->mask.offset[0];
  1187.         msk_y = r->mask.y + op->mask.offset[1];
  1188.         w = r->width;
  1189.         h = r->height;
  1190.  
  1191.         DBG(("%s: dst=(%d, %d), mask=(%f, %f) x (%f, %f)\n",
  1192.              __FUNCTION__, r->dst.x, r->dst.y, msk_x, msk_y, w, h));
  1193.  
  1194.         assert(op->floats_per_rect == 12);
  1195.         assert((sna->render.vertex_used % 4) == 0);
  1196.         v = sna->render.vertices + sna->render.vertex_used;
  1197.         sna->render.vertex_used += 12;
  1198.  
  1199.         dst.p.x = r->dst.x + r->width;
  1200.         dst.p.y = r->dst.y + r->height;
  1201.         v[0] = dst.f;
  1202.         v[2] = (msk_x + w) * op->mask.scale[0];
  1203.         v[7] = v[3] = (msk_y + h) * op->mask.scale[1];
  1204.  
  1205.         dst.p.x = r->dst.x;
  1206.         v[4] = dst.f;
  1207.         v[10] = v[6] = msk_x * op->mask.scale[0];
  1208.  
  1209.         dst.p.y = r->dst.y;
  1210.         v[8] = dst.f;
  1211.         v[11] = msk_y * op->mask.scale[1];
  1212.  
  1213.         v[9] = v[5] = v[1] = .5;
  1214. }
  1215.  
  1216. sse4_2 fastcall static void
  1217. emit_boxes_identity_mask__sse4_2(const struct sna_composite_op *op,
  1218.                                  const BoxRec *box, int nbox,
  1219.                                  float *v)
  1220. {
  1221.         float msk_x = op->mask.offset[0];
  1222.         float msk_y = op->mask.offset[1];
  1223.  
  1224.         do {
  1225.                 union {
  1226.                         struct sna_coordinate p;
  1227.                         float f;
  1228.                 } dst;
  1229.  
  1230.                 dst.p.x = box->x2;
  1231.                 dst.p.y = box->y2;
  1232.                 v[0] = dst.f;
  1233.                 v[2] = (msk_x + box->x2) * op->mask.scale[0];
  1234.                 v[7] = v[3] = (msk_y + box->y2) * op->mask.scale[1];
  1235.  
  1236.                 dst.p.x = box->x1;
  1237.                 v[4] = dst.f;
  1238.                 v[10] = v[6] = (msk_x + box->x1) * op->mask.scale[0];
  1239.  
  1240.                 dst.p.y = box->y1;
  1241.                 v[8] = dst.f;
  1242.                 v[11] = (msk_y + box->y1) * op->mask.scale[1];
  1243.  
  1244.                 v[9] = v[5] = v[1] = .5;
  1245.                 v += 12;
  1246.                 box++;
  1247.         } while (--nbox);
  1248. }
  1249.  
  1250. sse4_2 fastcall static void
  1251. emit_primitive_linear_identity_mask__sse4_2(struct sna *sna,
  1252.                                             const struct sna_composite_op *op,
  1253.                                             const struct sna_composite_rectangles *r)
  1254. {
  1255.         union {
  1256.                 struct sna_coordinate p;
  1257.                 float f;
  1258.         } dst;
  1259.         float msk_x, msk_y;
  1260.         float w, h;
  1261.         float *v;
  1262.  
  1263.         msk_x = r->mask.x + op->mask.offset[0];
  1264.         msk_y = r->mask.y + op->mask.offset[1];
  1265.         w = r->width;
  1266.         h = r->height;
  1267.  
  1268.         DBG(("%s: dst=(%d, %d), mask=(%f, %f) x (%f, %f)\n",
  1269.              __FUNCTION__, r->dst.x, r->dst.y, msk_x, msk_y, w, h));
  1270.  
  1271.         assert(op->floats_per_rect == 12);
  1272.         assert((sna->render.vertex_used % 4) == 0);
  1273.         v = sna->render.vertices + sna->render.vertex_used;
  1274.         sna->render.vertex_used += 12;
  1275.  
  1276.         dst.p.x = r->dst.x + r->width;
  1277.         dst.p.y = r->dst.y + r->height;
  1278.         v[0] = dst.f;
  1279.         v[2] = (msk_x + w) * op->mask.scale[0];
  1280.         v[7] = v[3] = (msk_y + h) * op->mask.scale[1];
  1281.  
  1282.         dst.p.x = r->dst.x;
  1283.         v[4] = dst.f;
  1284.         v[10] = v[6] = msk_x * op->mask.scale[0];
  1285.  
  1286.         dst.p.y = r->dst.y;
  1287.         v[8] = dst.f;
  1288.         v[11] = msk_y * op->mask.scale[1];
  1289.  
  1290.         v[1] = compute_linear(&op->src, r->src.x+r->width, r->src.y+r->height);
  1291.         v[5] = compute_linear(&op->src, r->src.x, r->src.y+r->height);
  1292.         v[9] = compute_linear(&op->src, r->src.x, r->src.y);
  1293. }
  1294.  
  1295. sse4_2 fastcall static void
  1296. emit_boxes_linear_identity_mask__sse4_2(const struct sna_composite_op *op,
  1297.                                         const BoxRec *box, int nbox,
  1298.                                         float *v)
  1299. {
  1300.         float msk_x = op->mask.offset[0];
  1301.         float msk_y = op->mask.offset[1];
  1302.  
  1303.         do {
  1304.                 union {
  1305.                         struct sna_coordinate p;
  1306.                         float f;
  1307.                 } dst;
  1308.  
  1309.                 dst.p.x = box->x2;
  1310.                 dst.p.y = box->y2;
  1311.                 v[0] = dst.f;
  1312.                 v[2] = (msk_x + box->x2) * op->mask.scale[0];
  1313.                 v[7] = v[3] = (msk_y + box->y2) * op->mask.scale[1];
  1314.  
  1315.                 dst.p.x = box->x1;
  1316.                 v[4] = dst.f;
  1317.                 v[10] = v[6] = (msk_x + box->x1) * op->mask.scale[0];
  1318.  
  1319.                 dst.p.y = box->y1;
  1320.                 v[8] = dst.f;
  1321.                 v[11] = (msk_y + box->y1) * op->mask.scale[1];
  1322.  
  1323.                 v[1] = compute_linear(&op->src, box->x2, box->y2);
  1324.                 v[5] = compute_linear(&op->src, box->x1, box->y2);
  1325.                 v[9] = compute_linear(&op->src, box->x1, box->y1);
  1326.  
  1327.                 v += 12;
  1328.                 box++;
  1329.         } while (--nbox);
  1330. }
  1331.  
  1332. #endif
  1333.  
  1334. /* AVX2 */
  1335. #if defined(avx2)
  1336.  
  1337. avx2 fastcall static void
  1338. emit_primitive_linear__avx2(struct sna *sna,
  1339.                             const struct sna_composite_op *op,
  1340.                             const struct sna_composite_rectangles *r)
  1341. {
  1342.         float *v;
  1343.         union {
  1344.                 struct sna_coordinate p;
  1345.                 float f;
  1346.         } dst;
  1347.  
  1348.         assert(op->floats_per_rect == 6);
  1349.         assert((sna->render.vertex_used % 2) == 0);
  1350.         v = sna->render.vertices + sna->render.vertex_used;
  1351.         sna->render.vertex_used += 6;
  1352.         assert(sna->render.vertex_used <= sna->render.vertex_size);
  1353.  
  1354.         dst.p.x = r->dst.x + r->width;
  1355.         dst.p.y = r->dst.y + r->height;
  1356.         v[0] = dst.f;
  1357.         dst.p.x = r->dst.x;
  1358.         v[2] = dst.f;
  1359.         dst.p.y = r->dst.y;
  1360.         v[4] = dst.f;
  1361.  
  1362.         v[1] = compute_linear(&op->src, r->src.x+r->width, r->src.y+r->height);
  1363.         v[3] = compute_linear(&op->src, r->src.x, r->src.y+r->height);
  1364.         v[5] = compute_linear(&op->src, r->src.x, r->src.y);
  1365. }
  1366.  
  1367. avx2 fastcall static void
  1368. emit_boxes_linear__avx2(const struct sna_composite_op *op,
  1369.                         const BoxRec *box, int nbox,
  1370.                         float *v)
  1371. {
  1372.         union {
  1373.                 struct sna_coordinate p;
  1374.                 float f;
  1375.         } dst;
  1376.  
  1377.         do {
  1378.                 dst.p.x = box->x2;
  1379.                 dst.p.y = box->y2;
  1380.                 v[0] = dst.f;
  1381.                 dst.p.x = box->x1;
  1382.                 v[2] = dst.f;
  1383.                 dst.p.y = box->y1;
  1384.                 v[4] = dst.f;
  1385.  
  1386.                 v[1] = compute_linear(&op->src, box->x2, box->y2);
  1387.                 v[3] = compute_linear(&op->src, box->x1, box->y2);
  1388.                 v[5] = compute_linear(&op->src, box->x1, box->y1);
  1389.  
  1390.                 v += 6;
  1391.                 box++;
  1392.         } while (--nbox);
  1393. }
  1394.  
  1395. avx2 fastcall static void
  1396. emit_primitive_identity_source__avx2(struct sna *sna,
  1397.                                      const struct sna_composite_op *op,
  1398.                                      const struct sna_composite_rectangles *r)
  1399. {
  1400.         union {
  1401.                 struct sna_coordinate p;
  1402.                 float f;
  1403.         } dst;
  1404.         float *v;
  1405.  
  1406.         assert(op->floats_per_rect == 9);
  1407.         assert((sna->render.vertex_used % 3) == 0);
  1408.         v = sna->render.vertices + sna->render.vertex_used;
  1409.         sna->render.vertex_used += 9;
  1410.  
  1411.         dst.p.x = r->dst.x + r->width;
  1412.         dst.p.y = r->dst.y + r->height;
  1413.         v[0] = dst.f;
  1414.         dst.p.x = r->dst.x;
  1415.         v[3] = dst.f;
  1416.         dst.p.y = r->dst.y;
  1417.         v[6] = dst.f;
  1418.  
  1419.         v[7] = v[4] = (r->src.x + op->src.offset[0]) * op->src.scale[0];
  1420.         v[1] = v[4] + r->width * op->src.scale[0];
  1421.  
  1422.         v[8] = (r->src.y + op->src.offset[1]) * op->src.scale[1];
  1423.         v[5] = v[2] = v[8] + r->height * op->src.scale[1];
  1424. }
  1425.  
  1426. avx2 fastcall static void
  1427. emit_boxes_identity_source__avx2(const struct sna_composite_op *op,
  1428.                                  const BoxRec *box, int nbox,
  1429.                                  float *v)
  1430. {
  1431.         do {
  1432.                 union {
  1433.                         struct sna_coordinate p;
  1434.                         float f;
  1435.                 } dst;
  1436.  
  1437.                 dst.p.x = box->x2;
  1438.                 dst.p.y = box->y2;
  1439.                 v[0] = dst.f;
  1440.                 dst.p.x = box->x1;
  1441.                 v[3] = dst.f;
  1442.                 dst.p.y = box->y1;
  1443.                 v[6] = dst.f;
  1444.  
  1445.                 v[7] = v[4] = (box->x1 + op->src.offset[0]) * op->src.scale[0];
  1446.                 v[1] = (box->x2 + op->src.offset[0]) * op->src.scale[0];
  1447.  
  1448.                 v[8] = (box->y1 + op->src.offset[1]) * op->src.scale[1];
  1449.                 v[2] = v[5] = (box->y2 + op->src.offset[1]) * op->src.scale[1];
  1450.  
  1451.                 v += 9;
  1452.                 box++;
  1453.         } while (--nbox);
  1454. }
  1455.  
  1456. avx2 fastcall static void
  1457. emit_primitive_simple_source__avx2(struct sna *sna,
  1458.                                    const struct sna_composite_op *op,
  1459.                                    const struct sna_composite_rectangles *r)
  1460. {
  1461.         float *v;
  1462.         union {
  1463.                 struct sna_coordinate p;
  1464.                 float f;
  1465.         } dst;
  1466.  
  1467.         float xx = op->src.transform->matrix[0][0];
  1468.         float x0 = op->src.transform->matrix[0][2];
  1469.         float yy = op->src.transform->matrix[1][1];
  1470.         float y0 = op->src.transform->matrix[1][2];
  1471.         float sx = op->src.scale[0];
  1472.         float sy = op->src.scale[1];
  1473.         int16_t tx = op->src.offset[0];
  1474.         int16_t ty = op->src.offset[1];
  1475.  
  1476.         assert(op->floats_per_rect == 9);
  1477.         assert((sna->render.vertex_used % 3) == 0);
  1478.         v = sna->render.vertices + sna->render.vertex_used;
  1479.         sna->render.vertex_used += 3*3;
  1480.  
  1481.         dst.p.x = r->dst.x + r->width;
  1482.         dst.p.y = r->dst.y + r->height;
  1483.         v[0] = dst.f;
  1484.         v[1] = ((r->src.x + r->width + tx) * xx + x0) * sx;
  1485.         v[5] = v[2] = ((r->src.y + r->height + ty) * yy + y0) * sy;
  1486.  
  1487.         dst.p.x = r->dst.x;
  1488.         v[3] = dst.f;
  1489.         v[7] = v[4] = ((r->src.x + tx) * xx + x0) * sx;
  1490.  
  1491.         dst.p.y = r->dst.y;
  1492.         v[6] = dst.f;
  1493.         v[8] = ((r->src.y + ty) * yy + y0) * sy;
  1494. }
  1495.  
  1496. avx2 fastcall static void
  1497. emit_boxes_simple_source__avx2(const struct sna_composite_op *op,
  1498.                                const BoxRec *box, int nbox,
  1499.                                float *v)
  1500. {
  1501.         float xx = op->src.transform->matrix[0][0];
  1502.         float x0 = op->src.transform->matrix[0][2];
  1503.         float yy = op->src.transform->matrix[1][1];
  1504.         float y0 = op->src.transform->matrix[1][2];
  1505.         float sx = op->src.scale[0];
  1506.         float sy = op->src.scale[1];
  1507.         int16_t tx = op->src.offset[0];
  1508.         int16_t ty = op->src.offset[1];
  1509.  
  1510.         do {
  1511.                 union {
  1512.                         struct sna_coordinate p;
  1513.                         float f;
  1514.                 } dst;
  1515.  
  1516.                 dst.p.x = box->x2;
  1517.                 dst.p.y = box->y2;
  1518.                 v[0] = dst.f;
  1519.                 v[1] = ((box->x2 + tx) * xx + x0) * sx;
  1520.                 v[5] = v[2] = ((box->y2 + ty) * yy + y0) * sy;
  1521.  
  1522.                 dst.p.x = box->x1;
  1523.                 v[3] = dst.f;
  1524.                 v[7] = v[4] = ((box->x1 + tx) * xx + x0) * sx;
  1525.  
  1526.                 dst.p.y = box->y1;
  1527.                 v[6] = dst.f;
  1528.                 v[8] = ((box->y1 + ty) * yy + y0) * sy;
  1529.  
  1530.                 v += 9;
  1531.                 box++;
  1532.         } while (--nbox);
  1533. }
  1534.  
  1535. avx2 fastcall static void
  1536. emit_primitive_identity_mask__avx2(struct sna *sna,
  1537.                                    const struct sna_composite_op *op,
  1538.                                    const struct sna_composite_rectangles *r)
  1539. {
  1540.         union {
  1541.                 struct sna_coordinate p;
  1542.                 float f;
  1543.         } dst;
  1544.         float msk_x, msk_y;
  1545.         float w, h;
  1546.         float *v;
  1547.  
  1548.         msk_x = r->mask.x + op->mask.offset[0];
  1549.         msk_y = r->mask.y + op->mask.offset[1];
  1550.         w = r->width;
  1551.         h = r->height;
  1552.  
  1553.         DBG(("%s: dst=(%d, %d), mask=(%f, %f) x (%f, %f)\n",
  1554.              __FUNCTION__, r->dst.x, r->dst.y, msk_x, msk_y, w, h));
  1555.  
  1556.         assert(op->floats_per_rect == 12);
  1557.         assert((sna->render.vertex_used % 4) == 0);
  1558.         v = sna->render.vertices + sna->render.vertex_used;
  1559.         sna->render.vertex_used += 12;
  1560.  
  1561.         dst.p.x = r->dst.x + r->width;
  1562.         dst.p.y = r->dst.y + r->height;
  1563.         v[0] = dst.f;
  1564.         v[2] = (msk_x + w) * op->mask.scale[0];
  1565.         v[7] = v[3] = (msk_y + h) * op->mask.scale[1];
  1566.  
  1567.         dst.p.x = r->dst.x;
  1568.         v[4] = dst.f;
  1569.         v[10] = v[6] = msk_x * op->mask.scale[0];
  1570.  
  1571.         dst.p.y = r->dst.y;
  1572.         v[8] = dst.f;
  1573.         v[11] = msk_y * op->mask.scale[1];
  1574.  
  1575.         v[9] = v[5] = v[1] = .5;
  1576. }
  1577.  
  1578. avx2 fastcall static void
  1579. emit_boxes_identity_mask__avx2(const struct sna_composite_op *op,
  1580.                                const BoxRec *box, int nbox,
  1581.                                float *v)
  1582. {
  1583.         float msk_x = op->mask.offset[0];
  1584.         float msk_y = op->mask.offset[1];
  1585.  
  1586.         do {
  1587.                 union {
  1588.                         struct sna_coordinate p;
  1589.                         float f;
  1590.                 } dst;
  1591.  
  1592.                 dst.p.x = box->x2;
  1593.                 dst.p.y = box->y2;
  1594.                 v[0] = dst.f;
  1595.                 v[2] = (msk_x + box->x2) * op->mask.scale[0];
  1596.                 v[7] = v[3] = (msk_y + box->y2) * op->mask.scale[1];
  1597.  
  1598.                 dst.p.x = box->x1;
  1599.                 v[4] = dst.f;
  1600.                 v[10] = v[6] = (msk_x + box->x1) * op->mask.scale[0];
  1601.  
  1602.                 dst.p.y = box->y1;
  1603.                 v[8] = dst.f;
  1604.                 v[11] = (msk_y + box->y1) * op->mask.scale[1];
  1605.  
  1606.                 v[9] = v[5] = v[1] = .5;
  1607.                 v += 12;
  1608.                 box++;
  1609.         } while (--nbox);
  1610. }
  1611.  
  1612. avx2 fastcall static void
  1613. emit_primitive_linear_identity_mask__avx2(struct sna *sna,
  1614.                                           const struct sna_composite_op *op,
  1615.                                           const struct sna_composite_rectangles *r)
  1616. {
  1617.         union {
  1618.                 struct sna_coordinate p;
  1619.                 float f;
  1620.         } dst;
  1621.         float msk_x, msk_y;
  1622.         float w, h;
  1623.         float *v;
  1624.  
  1625.         msk_x = r->mask.x + op->mask.offset[0];
  1626.         msk_y = r->mask.y + op->mask.offset[1];
  1627.         w = r->width;
  1628.         h = r->height;
  1629.  
  1630.         DBG(("%s: dst=(%d, %d), mask=(%f, %f) x (%f, %f)\n",
  1631.              __FUNCTION__, r->dst.x, r->dst.y, msk_x, msk_y, w, h));
  1632.  
  1633.         assert(op->floats_per_rect == 12);
  1634.         assert((sna->render.vertex_used % 4) == 0);
  1635.         v = sna->render.vertices + sna->render.vertex_used;
  1636.         sna->render.vertex_used += 12;
  1637.  
  1638.         dst.p.x = r->dst.x + r->width;
  1639.         dst.p.y = r->dst.y + r->height;
  1640.         v[0] = dst.f;
  1641.         v[2] = (msk_x + w) * op->mask.scale[0];
  1642.         v[7] = v[3] = (msk_y + h) * op->mask.scale[1];
  1643.  
  1644.         dst.p.x = r->dst.x;
  1645.         v[4] = dst.f;
  1646.         v[10] = v[6] = msk_x * op->mask.scale[0];
  1647.  
  1648.         dst.p.y = r->dst.y;
  1649.         v[8] = dst.f;
  1650.         v[11] = msk_y * op->mask.scale[1];
  1651.  
  1652.         v[1] = compute_linear(&op->src, r->src.x+r->width, r->src.y+r->height);
  1653.         v[5] = compute_linear(&op->src, r->src.x, r->src.y+r->height);
  1654.         v[9] = compute_linear(&op->src, r->src.x, r->src.y);
  1655. }
  1656.  
  1657. avx2 fastcall static void
  1658. emit_boxes_linear_identity_mask__avx2(const struct sna_composite_op *op,
  1659.                                       const BoxRec *box, int nbox,
  1660.                                       float *v)
  1661. {
  1662.         float msk_x = op->mask.offset[0];
  1663.         float msk_y = op->mask.offset[1];
  1664.  
  1665.         do {
  1666.                 union {
  1667.                         struct sna_coordinate p;
  1668.                         float f;
  1669.                 } dst;
  1670.  
  1671.                 dst.p.x = box->x2;
  1672.                 dst.p.y = box->y2;
  1673.                 v[0] = dst.f;
  1674.                 v[2] = (msk_x + box->x2) * op->mask.scale[0];
  1675.                 v[7] = v[3] = (msk_y + box->y2) * op->mask.scale[1];
  1676.  
  1677.                 dst.p.x = box->x1;
  1678.                 v[4] = dst.f;
  1679.                 v[10] = v[6] = (msk_x + box->x1) * op->mask.scale[0];
  1680.  
  1681.                 dst.p.y = box->y1;
  1682.                 v[8] = dst.f;
  1683.                 v[11] = (msk_y + box->y1) * op->mask.scale[1];
  1684.  
  1685.                 v[1] = compute_linear(&op->src, box->x2, box->y2);
  1686.                 v[5] = compute_linear(&op->src, box->x1, box->y2);
  1687.                 v[9] = compute_linear(&op->src, box->x1, box->y1);
  1688.  
  1689.                 v += 12;
  1690.                 box++;
  1691.         } while (--nbox);
  1692. }
  1693.  
  1694. #endif
  1695.  
  1696. unsigned gen4_choose_composite_emitter(struct sna *sna, struct sna_composite_op *tmp)
  1697. {
  1698.         unsigned vb;
  1699.  
  1700.         if (tmp->mask.bo) {
  1701.                 if (tmp->mask.transform == NULL) {
  1702.                         if (tmp->src.is_solid) {
  1703.                                 DBG(("%s: solid, identity mask\n", __FUNCTION__));
  1704. #if defined(avx2)
  1705.                                 if (sna->cpu_features & AVX2) {
  1706.                                         tmp->prim_emit = emit_primitive_identity_mask__avx2;
  1707.                                 } else
  1708. #endif
  1709. #if defined(sse4_2)
  1710.                                 if (sna->cpu_features & SSE4_2) {
  1711.                                         tmp->prim_emit = emit_primitive_identity_mask__sse4_2;
  1712.                                 } else
  1713. #endif
  1714.                                 {
  1715.                                         tmp->prim_emit = emit_primitive_identity_mask;
  1716.                                 }
  1717.                                 tmp->floats_per_vertex = 4;
  1718.                                 vb = 1 | 2 << 2;
  1719.                         } else if (tmp->src.is_linear) {
  1720.                                 DBG(("%s: linear, identity mask\n", __FUNCTION__));
  1721. #if defined(avx2)
  1722.                                 if (sna->cpu_features & AVX2) {
  1723.                                         tmp->prim_emit = emit_primitive_linear_identity_mask__avx2;
  1724.                                 } else
  1725. #endif
  1726. #if defined(sse4_2)
  1727.                                 if (sna->cpu_features & SSE4_2) {
  1728.                                         tmp->prim_emit = emit_primitive_linear_identity_mask__sse4_2;
  1729.                                 } else
  1730. #endif
  1731.                                 {
  1732.                                         tmp->prim_emit = emit_primitive_linear_identity_mask;
  1733.                                 }
  1734.                                 tmp->floats_per_vertex = 4;
  1735.                                 vb = 1 | 2 << 2;
  1736.                         } else if (tmp->src.transform == NULL) {
  1737.                                 DBG(("%s: identity source, identity mask\n", __FUNCTION__));
  1738.                                 tmp->prim_emit = emit_primitive_identity_source_mask;
  1739.                                 tmp->floats_per_vertex = 5;
  1740.                                 vb = 2 << 2 | 2;
  1741.                         } else if (tmp->src.is_affine) {
  1742.                                 tmp->src.scale[0] /= tmp->src.transform->matrix[2][2];
  1743.                                 tmp->src.scale[1] /= tmp->src.transform->matrix[2][2];
  1744.                                 if (!sna_affine_transform_is_rotation(tmp->src.transform)) {
  1745.                                         DBG(("%s: simple src, identity mask\n", __FUNCTION__));
  1746.                                         tmp->prim_emit = emit_primitive_simple_source_identity;
  1747.                                 } else {
  1748.                                         DBG(("%s: affine src, identity mask\n", __FUNCTION__));
  1749.                                         tmp->prim_emit = emit_primitive_affine_source_identity;
  1750.                                 }
  1751.                                 tmp->floats_per_vertex = 5;
  1752.                                 vb = 2 << 2 | 2;
  1753.                         } else {
  1754.                                 DBG(("%s: projective source, identity mask\n", __FUNCTION__));
  1755.                                 tmp->prim_emit = emit_primitive_mask;
  1756.                                 tmp->floats_per_vertex = 6;
  1757.                                 vb = 2 << 2 | 3;
  1758.                         }
  1759.                 } else {
  1760.                         tmp->prim_emit = emit_primitive_mask;
  1761.                         tmp->floats_per_vertex = 1;
  1762.                         vb = 0;
  1763.                         if (tmp->mask.is_solid) {
  1764.                                 tmp->floats_per_vertex += 1;
  1765.                                 vb |= 1 << 2;
  1766.                         } else if (tmp->mask.is_affine) {
  1767.                                 tmp->floats_per_vertex += 2;
  1768.                                 vb |= 2 << 2;
  1769.                         }else {
  1770.                                 tmp->floats_per_vertex += 3;
  1771.                                 vb |= 3 << 2;
  1772.                         }
  1773.                         if (tmp->src.is_solid) {
  1774.                                 tmp->floats_per_vertex += 1;
  1775.                                 vb |= 1;
  1776.                         } else if (tmp->src.is_affine) {
  1777.                                 tmp->floats_per_vertex += 2;
  1778.                                 vb |= 2 ;
  1779.                         }else {
  1780.                                 tmp->floats_per_vertex += 3;
  1781.                                 vb |= 3;
  1782.                         }
  1783.                         DBG(("%s: general mask: floats-per-vertex=%d, vb=%x\n",
  1784.                              __FUNCTION__,tmp->floats_per_vertex, vb));
  1785.                 }
  1786.         } else {
  1787. #if 0
  1788.                 if (tmp->src.is_solid) {
  1789.                         DBG(("%s: solid, no mask\n", __FUNCTION__));
  1790.                         tmp->prim_emit = emit_primitive_solid;
  1791.                         if (tmp->src.is_opaque && tmp->op == PictOpOver)
  1792.                                 tmp->op = PictOpSrc;
  1793.                         tmp->floats_per_vertex = 2;
  1794.                         vb = 1;
  1795.                 } else if (tmp->src.is_linear) {
  1796.                         DBG(("%s: linear, no mask\n", __FUNCTION__));
  1797. #if defined(avx2)
  1798.                         if (sna->cpu_features & AVX2) {
  1799.                                 tmp->prim_emit = emit_primitive_linear__avx2;
  1800.                         } else
  1801. #endif
  1802. #if defined(sse4_2)
  1803.                         if (sna->cpu_features & SSE4_2) {
  1804.                                 tmp->prim_emit = emit_primitive_linear__sse4_2;
  1805.                         } else
  1806. #endif
  1807.                         {
  1808.                                 tmp->prim_emit = emit_primitive_linear;
  1809.                         }
  1810.                         tmp->floats_per_vertex = 2;
  1811.                         vb = 1;
  1812.                 } else if (tmp->src.transform == NULL) {
  1813.                         DBG(("%s: identity src, no mask\n", __FUNCTION__));
  1814. #if defined(avx2)
  1815.                         if (sna->cpu_features & AVX2) {
  1816.                                 tmp->prim_emit = emit_primitive_identity_source__avx2;
  1817.                         } else
  1818. #endif
  1819. #if defined(sse4_2)
  1820.                         if (sna->cpu_features & SSE4_2) {
  1821.                                 tmp->prim_emit = emit_primitive_identity_source__sse4_2;
  1822.                         } else
  1823. #endif
  1824.                         {
  1825.                                 tmp->prim_emit = emit_primitive_identity_source;
  1826.                         }
  1827.                         tmp->floats_per_vertex = 3;
  1828.                         vb = 2;
  1829.                 } else if (tmp->src.is_affine) {
  1830.                         tmp->src.scale[0] /= tmp->src.transform->matrix[2][2];
  1831.                         tmp->src.scale[1] /= tmp->src.transform->matrix[2][2];
  1832.                         if (!sna_affine_transform_is_rotation(tmp->src.transform)) {
  1833.                                 DBG(("%s: simple src, no mask\n", __FUNCTION__));
  1834. #if defined(avx2)
  1835.                                 if (sna->cpu_features & AVX2) {
  1836.                                         tmp->prim_emit = emit_primitive_simple_source__avx2;
  1837.                                 } else
  1838. #endif
  1839. #if defined(sse4_2)
  1840.                                 if (sna->cpu_features & SSE4_2) {
  1841.                                         tmp->prim_emit = emit_primitive_simple_source__sse4_2;
  1842.                                 } else
  1843. #endif
  1844.                                 {
  1845.                                         tmp->prim_emit = emit_primitive_simple_source;
  1846.                                 }
  1847.                         } else {
  1848.                                 DBG(("%s: affine src, no mask\n", __FUNCTION__));
  1849.                                 tmp->prim_emit = emit_primitive_affine_source;
  1850.                         }
  1851.                         tmp->floats_per_vertex = 3;
  1852.                         vb = 2;
  1853.                 } else {
  1854.                         DBG(("%s: projective src, no mask\n", __FUNCTION__));
  1855.                         assert(!tmp->src.is_solid);
  1856.                         tmp->prim_emit = emit_primitive;
  1857.                         tmp->floats_per_vertex = 4;
  1858.                         vb = 3;
  1859.                 }
  1860. #endif
  1861.         }
  1862.         tmp->floats_per_rect = 3 * tmp->floats_per_vertex;
  1863.  
  1864.         return vb;
  1865. }
  1866.  
  1867.  
  1868.  
  1869.