Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Copyright © 2004 Keith Packard
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and its
  5.  * documentation for any purpose is hereby granted without fee, provided that
  6.  * the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of Keith Packard not be used in
  9.  * advertising or publicity pertaining to distribution of the software without
  10.  * specific, written prior permission.  Keith Packard makes no
  11.  * representations about the suitability of this software for any purpose.  It
  12.  * is provided "as is" without express or implied warranty.
  13.  *
  14.  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  16.  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  19.  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  20.  * PERFORMANCE OF THIS SOFTWARE.
  21.  */
  22.  
  23. #ifdef HAVE_CONFIG_H
  24. #include <config.h>
  25. #endif
  26.  
  27. #include <string.h>
  28.  
  29. #include "pixman-private.h"
  30. #include "pixman-accessor.h"
  31.  
  32. /*
  33.  * Step across a small sample grid gap
  34.  */
  35. #define RENDER_EDGE_STEP_SMALL(edge)                                    \
  36.     {                                                                   \
  37.         edge->x += edge->stepx_small;                                   \
  38.         edge->e += edge->dx_small;                                      \
  39.         if (edge->e > 0)                                                \
  40.         {                                                               \
  41.             edge->e -= edge->dy;                                        \
  42.             edge->x += edge->signdx;                                    \
  43.         }                                                               \
  44.     }
  45.  
  46. /*
  47.  * Step across a large sample grid gap
  48.  */
  49. #define RENDER_EDGE_STEP_BIG(edge)                                      \
  50.     {                                                                   \
  51.         edge->x += edge->stepx_big;                                     \
  52.         edge->e += edge->dx_big;                                        \
  53.         if (edge->e > 0)                                                \
  54.         {                                                               \
  55.             edge->e -= edge->dy;                                        \
  56.             edge->x += edge->signdx;                                    \
  57.         }                                                               \
  58.     }
  59.  
  60. #ifdef PIXMAN_FB_ACCESSORS
  61. #define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_accessors
  62. #else
  63. #define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_no_accessors
  64. #endif
  65.  
  66. /*
  67.  * 4 bit alpha
  68.  */
  69.  
  70. #define N_BITS  4
  71. #define RASTERIZE_EDGES rasterize_edges_4
  72.  
  73. #ifndef WORDS_BIGENDIAN
  74. #define SHIFT_4(o)      ((o) << 2)
  75. #else
  76. #define SHIFT_4(o)      ((1 - (o)) << 2)
  77. #endif
  78.  
  79. #define GET_4(x, o)      (((x) >> SHIFT_4 (o)) & 0xf)
  80. #define PUT_4(x, o, v)                                                  \
  81.     (((x) & ~(0xf << SHIFT_4 (o))) | (((v) & 0xf) << SHIFT_4 (o)))
  82.  
  83. #define DEFINE_ALPHA(line, x)                                           \
  84.     uint8_t   *__ap = (uint8_t *) line + ((x) >> 1);                    \
  85.     int __ao = (x) & 1
  86.  
  87. #define STEP_ALPHA      ((__ap += __ao), (__ao ^= 1))
  88.  
  89. #define ADD_ALPHA(a)                                                    \
  90.     {                                                                   \
  91.         uint8_t __o = READ (image, __ap);                               \
  92.         uint8_t __a = (a) + GET_4 (__o, __ao);                          \
  93.         WRITE (image, __ap, PUT_4 (__o, __ao, __a | (0 - ((__a) >> 4)))); \
  94.     }
  95.  
  96. #include "pixman-edge-imp.h"
  97.  
  98. #undef ADD_ALPHA
  99. #undef STEP_ALPHA
  100. #undef DEFINE_ALPHA
  101. #undef RASTERIZE_EDGES
  102. #undef N_BITS
  103.  
  104.  
  105. /*
  106.  * 1 bit alpha
  107.  */
  108.  
  109. #define N_BITS 1
  110. #define RASTERIZE_EDGES rasterize_edges_1
  111.  
  112. #include "pixman-edge-imp.h"
  113.  
  114. #undef RASTERIZE_EDGES
  115. #undef N_BITS
  116.  
  117. /*
  118.  * 8 bit alpha
  119.  */
  120.  
  121. static force_inline uint8_t
  122. clip255 (int x)
  123. {
  124.     if (x > 255)
  125.         return 255;
  126.  
  127.     return x;
  128. }
  129.  
  130. #define ADD_SATURATE_8(buf, val, length)                                \
  131.     do                                                                  \
  132.     {                                                                   \
  133.         int i__ = (length);                                             \
  134.         uint8_t *buf__ = (buf);                                         \
  135.         int val__ = (val);                                              \
  136.                                                                         \
  137.         while (i__--)                                                   \
  138.         {                                                               \
  139.             WRITE (image, (buf__), clip255 (READ (image, (buf__)) + (val__))); \
  140.             (buf__)++;                                                  \
  141.         }                                                               \
  142.     } while (0)
  143.  
  144. /*
  145.  * We want to detect the case where we add the same value to a long
  146.  * span of pixels.  The triangles on the end are filled in while we
  147.  * count how many sub-pixel scanlines contribute to the middle section.
  148.  *
  149.  *                 +--------------------------+
  150.  *  fill_height =|   \                      /
  151.  *                     +------------------+
  152.  *                      |================|
  153.  *                   fill_start       fill_end
  154.  */
  155. static void
  156. rasterize_edges_8 (pixman_image_t *image,
  157.                    pixman_edge_t * l,
  158.                    pixman_edge_t * r,
  159.                    pixman_fixed_t  t,
  160.                    pixman_fixed_t  b)
  161. {
  162.     pixman_fixed_t y = t;
  163.     uint32_t  *line;
  164.     int fill_start = -1, fill_end = -1;
  165.     int fill_size = 0;
  166.     uint32_t *buf = (image)->bits.bits;
  167.     int stride = (image)->bits.rowstride;
  168.     int width = (image)->bits.width;
  169.  
  170.     line = buf + pixman_fixed_to_int (y) * stride;
  171.  
  172.     for (;;)
  173.     {
  174.         uint8_t *ap = (uint8_t *) line;
  175.         pixman_fixed_t lx, rx;
  176.         int lxi, rxi;
  177.  
  178.         /* clip X */
  179.         lx = l->x;
  180.         if (lx < 0)
  181.             lx = 0;
  182.  
  183.         rx = r->x;
  184.  
  185.         if (pixman_fixed_to_int (rx) >= width)
  186.         {
  187.             /* Use the last pixel of the scanline, covered 100%.
  188.              * We can't use the first pixel following the scanline,
  189.              * because accessing it could result in a buffer overrun.
  190.              */
  191.             rx = pixman_int_to_fixed (width) - 1;
  192.         }
  193.  
  194.         /* Skip empty (or backwards) sections */
  195.         if (rx > lx)
  196.         {
  197.             int lxs, rxs;
  198.  
  199.             /* Find pixel bounds for span. */
  200.             lxi = pixman_fixed_to_int (lx);
  201.             rxi = pixman_fixed_to_int (rx);
  202.  
  203.             /* Sample coverage for edge pixels */
  204.             lxs = RENDER_SAMPLES_X (lx, 8);
  205.             rxs = RENDER_SAMPLES_X (rx, 8);
  206.  
  207.             /* Add coverage across row */
  208.             if (lxi == rxi)
  209.             {
  210.                 WRITE (image, ap + lxi,
  211.                        clip255 (READ (image, ap + lxi) + rxs - lxs));
  212.             }
  213.             else
  214.             {
  215.                 WRITE (image, ap + lxi,
  216.                        clip255 (READ (image, ap + lxi) + N_X_FRAC (8) - lxs));
  217.  
  218.                 /* Move forward so that lxi/rxi is the pixel span */
  219.                 lxi++;
  220.  
  221.                 /* Don't bother trying to optimize the fill unless
  222.                  * the span is longer than 4 pixels. */
  223.                 if (rxi - lxi > 4)
  224.                 {
  225.                     if (fill_start < 0)
  226.                     {
  227.                         fill_start = lxi;
  228.                         fill_end = rxi;
  229.                         fill_size++;
  230.                     }
  231.                     else
  232.                     {
  233.                         if (lxi >= fill_end || rxi < fill_start)
  234.                         {
  235.                             /* We're beyond what we saved, just fill it */
  236.                             ADD_SATURATE_8 (ap + fill_start,
  237.                                             fill_size * N_X_FRAC (8),
  238.                                             fill_end - fill_start);
  239.                             fill_start = lxi;
  240.                             fill_end = rxi;
  241.                             fill_size = 1;
  242.                         }
  243.                         else
  244.                         {
  245.                             /* Update fill_start */
  246.                             if (lxi > fill_start)
  247.                             {
  248.                                 ADD_SATURATE_8 (ap + fill_start,
  249.                                                 fill_size * N_X_FRAC (8),
  250.                                                 lxi - fill_start);
  251.                                 fill_start = lxi;
  252.                             }
  253.                             else if (lxi < fill_start)
  254.                             {
  255.                                 ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8),
  256.                                                 fill_start - lxi);
  257.                             }
  258.  
  259.                             /* Update fill_end */
  260.                             if (rxi < fill_end)
  261.                             {
  262.                                 ADD_SATURATE_8 (ap + rxi,
  263.                                                 fill_size * N_X_FRAC (8),
  264.                                                 fill_end - rxi);
  265.                                 fill_end = rxi;
  266.                             }
  267.                             else if (fill_end < rxi)
  268.                             {
  269.                                 ADD_SATURATE_8 (ap + fill_end,
  270.                                                 N_X_FRAC (8),
  271.                                                 rxi - fill_end);
  272.                             }
  273.                             fill_size++;
  274.                         }
  275.                     }
  276.                 }
  277.                 else
  278.                 {
  279.                     ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8), rxi - lxi);
  280.                 }
  281.  
  282.                 WRITE (image, ap + rxi, clip255 (READ (image, ap + rxi) + rxs));
  283.             }
  284.         }
  285.  
  286.         if (y == b)
  287.         {
  288.             /* We're done, make sure we clean up any remaining fill. */
  289.             if (fill_start != fill_end)
  290.             {
  291.                 if (fill_size == N_Y_FRAC (8))
  292.                 {
  293.                     MEMSET_WRAPPED (image, ap + fill_start,
  294.                                     0xff, fill_end - fill_start);
  295.                 }
  296.                 else
  297.                 {
  298.                     ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8),
  299.                                     fill_end - fill_start);
  300.                 }
  301.             }
  302.             break;
  303.         }
  304.  
  305.         if (pixman_fixed_frac (y) != Y_FRAC_LAST (8))
  306.         {
  307.             RENDER_EDGE_STEP_SMALL (l);
  308.             RENDER_EDGE_STEP_SMALL (r);
  309.             y += STEP_Y_SMALL (8);
  310.         }
  311.         else
  312.         {
  313.             RENDER_EDGE_STEP_BIG (l);
  314.             RENDER_EDGE_STEP_BIG (r);
  315.             y += STEP_Y_BIG (8);
  316.             if (fill_start != fill_end)
  317.             {
  318.                 if (fill_size == N_Y_FRAC (8))
  319.                 {
  320.                     MEMSET_WRAPPED (image, ap + fill_start,
  321.                                     0xff, fill_end - fill_start);
  322.                 }
  323.                 else
  324.                 {
  325.                     ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8),
  326.                                     fill_end - fill_start);
  327.                 }
  328.                
  329.                 fill_start = fill_end = -1;
  330.                 fill_size = 0;
  331.             }
  332.            
  333.             line += stride;
  334.         }
  335.     }
  336. }
  337.  
  338. #ifndef PIXMAN_FB_ACCESSORS
  339. static
  340. #endif
  341. void
  342. PIXMAN_RASTERIZE_EDGES (pixman_image_t *image,
  343.                         pixman_edge_t * l,
  344.                         pixman_edge_t * r,
  345.                         pixman_fixed_t  t,
  346.                         pixman_fixed_t  b)
  347. {
  348.     switch (PIXMAN_FORMAT_BPP (image->bits.format))
  349.     {
  350.     case 1:
  351.         rasterize_edges_1 (image, l, r, t, b);
  352.         break;
  353.  
  354.     case 4:
  355.         rasterize_edges_4 (image, l, r, t, b);
  356.         break;
  357.  
  358.     case 8:
  359.         rasterize_edges_8 (image, l, r, t, b);
  360.         break;
  361.  
  362.     default:
  363.         break;
  364.     }
  365. }
  366.  
  367. #ifndef PIXMAN_FB_ACCESSORS
  368.  
  369. PIXMAN_EXPORT void
  370. pixman_rasterize_edges (pixman_image_t *image,
  371.                         pixman_edge_t * l,
  372.                         pixman_edge_t * r,
  373.                         pixman_fixed_t  t,
  374.                         pixman_fixed_t  b)
  375. {
  376.     return_if_fail (image->type == BITS);
  377.     return_if_fail (PIXMAN_FORMAT_TYPE (image->bits.format) == PIXMAN_TYPE_A);
  378.    
  379.     if (image->bits.read_func || image->bits.write_func)
  380.         pixman_rasterize_edges_accessors (image, l, r, t, b);
  381.     else
  382.         pixman_rasterize_edges_no_accessors (image, l, r, t, b);
  383. }
  384.  
  385. #endif
  386.