Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Copyright © 2009 Red Hat, Inc.
  3.  * Copyright © 2000 SuSE, Inc.
  4.  * Copyright © 2007 Red Hat, Inc.
  5.  * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
  6.  *             2005 Lars Knoll & Zack Rusin, Trolltech
  7.  *             2008 Aaron Plattner, NVIDIA Corporation
  8.  *
  9.  * Permission to use, copy, modify, distribute, and sell this software and its
  10.  * documentation for any purpose is hereby granted without fee, provided that
  11.  * the above copyright notice appear in all copies and that both that
  12.  * copyright notice and this permission notice appear in supporting
  13.  * documentation, and that the name of Red Hat not be used in advertising or
  14.  * publicity pertaining to distribution of the software without specific,
  15.  * written prior permission.  Red Hat makes no representations about the
  16.  * suitability of this software for any purpose.  It is provided "as is"
  17.  * without express or implied warranty.
  18.  *
  19.  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
  20.  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  21.  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
  22.  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  23.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  24.  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
  25.  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  26.  * SOFTWARE.
  27.  */
  28. #ifdef HAVE_CONFIG_H
  29. #include <config.h>
  30. #endif
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <math.h>
  34. #include <limits.h>
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <string.h>
  38. #include "pixman-private.h"
  39. #include "pixman-combine32.h"
  40. #include "pixman-private.h"
  41.  
  42. #define SCANLINE_BUFFER_LENGTH 8192
  43.  
  44. static void
  45. general_composite_rect  (pixman_implementation_t *imp,
  46.                          pixman_op_t              op,
  47.                          pixman_image_t *         src,
  48.                          pixman_image_t *         mask,
  49.                          pixman_image_t *         dest,
  50.                          int32_t                  src_x,
  51.                          int32_t                  src_y,
  52.                          int32_t                  mask_x,
  53.                          int32_t                  mask_y,
  54.                          int32_t                  dest_x,
  55.                          int32_t                  dest_y,
  56.                          int32_t                  width,
  57.                          int32_t                  height)
  58. {
  59.     uint64_t stack_scanline_buffer[(SCANLINE_BUFFER_LENGTH * 3 + 7) / 8];
  60.     uint8_t *scanline_buffer = (uint8_t *) stack_scanline_buffer;
  61.     uint8_t *src_buffer, *mask_buffer, *dest_buffer;
  62.     fetch_scanline_t fetch_src = NULL, fetch_mask = NULL, fetch_dest = NULL;
  63.     pixman_combine_32_func_t compose;
  64.     store_scanline_t store;
  65.     source_image_class_t src_class, mask_class;
  66.     pixman_bool_t component_alpha;
  67.     uint32_t *bits;
  68.     int32_t stride;
  69.     int narrow, Bpp;
  70.     int i;
  71.  
  72.     narrow =
  73.         (src->common.flags & FAST_PATH_NARROW_FORMAT)           &&
  74.         (!mask || mask->common.flags & FAST_PATH_NARROW_FORMAT) &&
  75.         (dest->common.flags & FAST_PATH_NARROW_FORMAT);
  76.     Bpp = narrow ? 4 : 8;
  77.  
  78.     if (width * Bpp > SCANLINE_BUFFER_LENGTH)
  79.     {
  80.         scanline_buffer = pixman_malloc_abc (width, 3, Bpp);
  81.  
  82.         if (!scanline_buffer)
  83.             return;
  84.     }
  85.  
  86.     src_buffer = scanline_buffer;
  87.     mask_buffer = src_buffer + width * Bpp;
  88.     dest_buffer = mask_buffer + width * Bpp;
  89.  
  90.     src_class = _pixman_image_classify (src,
  91.                                         src_x, src_y,
  92.                                         width, height);
  93.  
  94.     mask_class = SOURCE_IMAGE_CLASS_UNKNOWN;
  95.  
  96.     if (mask)
  97.     {
  98.         mask_class = _pixman_image_classify (mask,
  99.                                              src_x, src_y,
  100.                                              width, height);
  101.     }
  102.  
  103.     if (op == PIXMAN_OP_CLEAR)
  104.         fetch_src = NULL;
  105.     else if (narrow)
  106.         fetch_src = _pixman_image_get_scanline_32;
  107.     else
  108.         fetch_src = _pixman_image_get_scanline_64;
  109.  
  110.     if (!mask || op == PIXMAN_OP_CLEAR)
  111.         fetch_mask = NULL;
  112.     else if (narrow)
  113.         fetch_mask = _pixman_image_get_scanline_32;
  114.     else
  115.         fetch_mask = _pixman_image_get_scanline_64;
  116.  
  117.     if (op == PIXMAN_OP_CLEAR || op == PIXMAN_OP_SRC)
  118.         fetch_dest = NULL;
  119.     else if (narrow)
  120.         fetch_dest = _pixman_image_get_scanline_32;
  121.     else
  122.         fetch_dest = _pixman_image_get_scanline_64;
  123.  
  124.     if (narrow)
  125.         store = _pixman_image_store_scanline_32;
  126.     else
  127.         store = _pixman_image_store_scanline_64;
  128.  
  129.     /* Skip the store step and composite directly into the
  130.      * destination if the output format of the compose func matches
  131.      * the destination format.
  132.      *
  133.      * If the destination format is a8r8g8b8 then we can always do
  134.      * this. If it is x8r8g8b8, then we can only do it if the
  135.      * operator doesn't make use of destination alpha.
  136.      */
  137.     if ((dest->bits.format == PIXMAN_a8r8g8b8)  ||
  138.         (dest->bits.format == PIXMAN_x8r8g8b8   &&
  139.          (op == PIXMAN_OP_OVER          ||
  140.           op == PIXMAN_OP_ADD           ||
  141.           op == PIXMAN_OP_SRC           ||
  142.           op == PIXMAN_OP_CLEAR         ||
  143.           op == PIXMAN_OP_IN_REVERSE    ||
  144.           op == PIXMAN_OP_OUT_REVERSE   ||
  145.           op == PIXMAN_OP_DST)))
  146.     {
  147.         if (narrow &&
  148.             !dest->common.alpha_map &&
  149.             !dest->bits.write_func)
  150.         {
  151.             store = NULL;
  152.         }
  153.     }
  154.  
  155.     if (!store)
  156.     {
  157.         bits = dest->bits.bits;
  158.         stride = dest->bits.rowstride;
  159.     }
  160.     else
  161.     {
  162.         bits = NULL;
  163.         stride = 0;
  164.     }
  165.  
  166.     component_alpha =
  167.         fetch_src                       &&
  168.         fetch_mask                      &&
  169.         mask                            &&
  170.         mask->common.type == BITS       &&
  171.         mask->common.component_alpha    &&
  172.         PIXMAN_FORMAT_RGB (mask->bits.format);
  173.  
  174.     if (narrow)
  175.     {
  176.         if (component_alpha)
  177.             compose = _pixman_implementation_combine_32_ca;
  178.         else
  179.             compose = _pixman_implementation_combine_32;
  180.     }
  181.     else
  182.     {
  183.         if (component_alpha)
  184.             compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64_ca;
  185.         else
  186.             compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64;
  187.     }
  188.  
  189.     if (!compose)
  190.         return;
  191.  
  192.     if (!fetch_mask)
  193.         mask_buffer = NULL;
  194.  
  195.     for (i = 0; i < height; ++i)
  196.     {
  197.         /* fill first half of scanline with source */
  198.         if (fetch_src)
  199.         {
  200.             if (fetch_mask)
  201.             {
  202.                 /* fetch mask before source so that fetching of
  203.                    source can be optimized */
  204.                 fetch_mask (mask, mask_x, mask_y + i,
  205.                             width, (void *)mask_buffer, 0);
  206.  
  207.                 if (mask_class == SOURCE_IMAGE_CLASS_HORIZONTAL)
  208.                     fetch_mask = NULL;
  209.             }
  210.  
  211.             if (src_class == SOURCE_IMAGE_CLASS_HORIZONTAL)
  212.             {
  213.                 fetch_src (src, src_x, src_y + i,
  214.                            width, (void *)src_buffer, 0);
  215.                 fetch_src = NULL;
  216.             }
  217.             else
  218.             {
  219.                 fetch_src (src, src_x, src_y + i,
  220.                            width, (void *)src_buffer, (void *)mask_buffer);
  221.             }
  222.         }
  223.         else if (fetch_mask)
  224.         {
  225.             fetch_mask (mask, mask_x, mask_y + i,
  226.                         width, (void *)mask_buffer, 0);
  227.         }
  228.  
  229.         if (store)
  230.         {
  231.             /* fill dest into second half of scanline */
  232.             if (fetch_dest)
  233.             {
  234.                 fetch_dest (dest, dest_x, dest_y + i,
  235.                             width, (void *)dest_buffer, 0);
  236.             }
  237.  
  238.             /* blend */
  239.             compose (imp->toplevel, op,
  240.                      (void *)dest_buffer,
  241.                      (void *)src_buffer,
  242.                      (void *)mask_buffer,
  243.                      width);
  244.  
  245.             /* write back */
  246.             store (&(dest->bits), dest_x, dest_y + i, width,
  247.                    (void *)dest_buffer);
  248.         }
  249.         else
  250.         {
  251.             /* blend */
  252.             compose (imp->toplevel, op,
  253.                      bits + (dest_y + i) * stride + dest_x,
  254.                      (void *)src_buffer, (void *)mask_buffer, width);
  255.         }
  256.     }
  257.  
  258.     if (scanline_buffer != (uint8_t *) stack_scanline_buffer)
  259.         free (scanline_buffer);
  260. }
  261.  
  262. static const pixman_fast_path_t general_fast_path[] =
  263. {
  264.     { PIXMAN_OP_any, PIXMAN_any, 0, PIXMAN_any, 0, PIXMAN_any, 0, general_composite_rect },
  265.     { PIXMAN_OP_NONE }
  266. };
  267.  
  268. static pixman_bool_t
  269. general_blt (pixman_implementation_t *imp,
  270.              uint32_t *               src_bits,
  271.              uint32_t *               dst_bits,
  272.              int                      src_stride,
  273.              int                      dst_stride,
  274.              int                      src_bpp,
  275.              int                      dst_bpp,
  276.              int                      src_x,
  277.              int                      src_y,
  278.              int                      dst_x,
  279.              int                      dst_y,
  280.              int                      width,
  281.              int                      height)
  282. {
  283.     /* We can't blit unless we have sse2 or mmx */
  284.  
  285.     return FALSE;
  286. }
  287.  
  288. static pixman_bool_t
  289. general_fill (pixman_implementation_t *imp,
  290.               uint32_t *               bits,
  291.               int                      stride,
  292.               int                      bpp,
  293.               int                      x,
  294.               int                      y,
  295.               int                      width,
  296.               int                      height,
  297.               uint32_t xor)
  298. {
  299.     return FALSE;
  300. }
  301.  
  302. pixman_implementation_t *
  303. _pixman_implementation_create_general (void)
  304. {
  305.     pixman_implementation_t *imp = _pixman_implementation_create (NULL, general_fast_path);
  306.  
  307.     _pixman_setup_combiner_functions_32 (imp);
  308.     _pixman_setup_combiner_functions_64 (imp);
  309.  
  310.     imp->blt = general_blt;
  311.     imp->fill = general_fill;
  312.  
  313.     return imp;
  314. }
  315.  
  316.