mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-30 20:37:31 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
0
gfx/cairo/libpixman/AUTHORS
Normal file
0
gfx/cairo/libpixman/AUTHORS
Normal file
0
gfx/cairo/libpixman/COPYING
Normal file
0
gfx/cairo/libpixman/COPYING
Normal file
234
gfx/cairo/libpixman/INSTALL
Normal file
234
gfx/cairo/libpixman/INSTALL
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
|
||||
2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is free documentation; the Free Software Foundation gives
|
||||
unlimited permission to copy, distribute and modify it.
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
Briefly, the shell commands `./configure; make; make install' should
|
||||
configure, build, and install this package. The following
|
||||
more-detailed instructions are generic; see the `README' file for
|
||||
instructions specific to this package.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a `Makefile' in each directory of the package.
|
||||
It may also create one or more `.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script `config.status' that
|
||||
you can run in the future to recreate the current configuration, and a
|
||||
file `config.log' containing compiler output (useful mainly for
|
||||
debugging `configure').
|
||||
|
||||
It can also use an optional file (typically called `config.cache'
|
||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||
the results of its tests to speed up reconfiguring. Caching is
|
||||
disabled by default to prevent problems with accidental use of stale
|
||||
cache files.
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the `README' so they can
|
||||
be considered for the next release. If you are using the cache, and at
|
||||
some point `config.cache' contains results you don't want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The file `configure.ac' (or `configure.in') is used to create
|
||||
`configure' by a program called `autoconf'. You need `configure.ac' if
|
||||
you want to change it or regenerate `configure' using a newer version
|
||||
of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system.
|
||||
|
||||
Running `configure' might take a while. While running, it prints
|
||||
some messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
|
||||
3. Optionally, type `make check' to run any self-tests that come with
|
||||
the package.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation.
|
||||
|
||||
5. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'. There is
|
||||
also a `make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that the
|
||||
`configure' script does not know about. Run `./configure --help' for
|
||||
details on some of the pertinent environment variables.
|
||||
|
||||
You can give `configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here
|
||||
is an example:
|
||||
|
||||
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
||||
|
||||
*Note Defining Variables::, for more details.
|
||||
|
||||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you can use GNU `make'. `cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'.
|
||||
|
||||
With a non-GNU `make', it is safer to compile the package for one
|
||||
architecture at a time in the source code directory. After you have
|
||||
installed the package for one architecture, use `make distclean' before
|
||||
reconfiguring for another architecture.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' installs the package's commands under
|
||||
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||
can specify an installation prefix other than `/usr/local' by giving
|
||||
`configure' the option `--prefix=PREFIX'.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||
PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=DIR' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them.
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
`README' should mention any `--enable-' and `--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, `configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' cannot figure out automatically,
|
||||
but needs to determine by the type of machine the package will run on.
|
||||
Usually, assuming the package is built to be run on the _same_
|
||||
architectures, `configure' can figure that out, but if it prints a
|
||||
message saying it cannot guess the machine type, give it the
|
||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name which has the form:
|
||||
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
where SYSTEM can have one of these forms:
|
||||
|
||||
OS KERNEL-OS
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the machine type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the option `--target=TYPE' to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
platform different from the build platform, you should specify the
|
||||
"host" platform (i.e., that on which the generated programs will
|
||||
eventually be run) with `--host=TYPE'.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share, you
|
||||
can create a site shell script called `config.site' that gives default
|
||||
values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all `configure' scripts look for a site script.
|
||||
|
||||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to `configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
them in the `configure' command line, using `VAR=value'. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||
overridden in the site shell script).
|
||||
|
||||
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
||||
an Autoconf bug. Until the bug is fixed you can use this workaround:
|
||||
|
||||
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
|
||||
`configure' Invocation
|
||||
======================
|
||||
|
||||
`configure' recognizes the following options to control how it operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
Print a summary of the options to `configure', and exit.
|
||||
|
||||
`--version'
|
||||
`-V'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Enable the cache: use and save the results of the tests in FILE,
|
||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||
disable caching.
|
||||
|
||||
`--config-cache'
|
||||
`-C'
|
||||
Alias for `--cache-file=config.cache'.
|
||||
|
||||
`--quiet'
|
||||
`--silent'
|
||||
`-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to `/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
`--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options. Run
|
||||
`configure --help' for more details.
|
||||
|
||||
0
gfx/cairo/libpixman/NEWS
Normal file
0
gfx/cairo/libpixman/NEWS
Normal file
0
gfx/cairo/libpixman/README
Normal file
0
gfx/cairo/libpixman/README
Normal file
139
gfx/cairo/libpixman/TODO
Normal file
139
gfx/cairo/libpixman/TODO
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
- Go through things marked FIXME
|
||||
|
||||
- Add calls to prepare and finish access where necessary. grep for
|
||||
ACCESS_MEM, and make sure they are correctly wrapped in prepare
|
||||
and finish.
|
||||
|
||||
- restore READ/WRITE in the fbcompose combiners since they sometimes
|
||||
store directly to destination drawables.
|
||||
|
||||
- It probably makes sense to move the more strange X region API
|
||||
into pixman as well, but guarded with PIXMAN_XORG_COMPATIBILITY
|
||||
|
||||
- Reinstate the FbBits typedef? At the moment we don't
|
||||
even have the FbBits type; we just use uint32_t everywhere.
|
||||
|
||||
Keith says in bug 2335:
|
||||
|
||||
The 64-bit code in fb (pixman) is probably broken; it hasn't been
|
||||
used in quite some time as PCI (and AGP) is 32-bits wide, so
|
||||
doing things 64-bits at a time is a net loss. To quickly fix
|
||||
this, I suggest just using 32-bit datatypes by setting
|
||||
IC_SHIFT to 5 for all machines.
|
||||
|
||||
- Consider whether calling regions region16 is really such a great
|
||||
idea Vlad wants 32 bit regions for Cairo. This will break X server
|
||||
ABI, but should otherwise be mostly harmless, though a
|
||||
pixman_region_get_boxes16() may be useful.
|
||||
|
||||
- Make source clipping optional.
|
||||
- done: source clipping happens through an indirection.
|
||||
still needs to make the indirection settable. (And call it
|
||||
from X)
|
||||
|
||||
- Consider optimizing the 8/16 bit solid fills in pixman-util.c by
|
||||
storing more than one value at a time.
|
||||
|
||||
- Add an image cache to prevent excessive malloc/free. Note that pixman
|
||||
needs to be thread safe when used from cairo.
|
||||
|
||||
- Review the pixman_format_code_t enum to make sure it will support
|
||||
future formats. Some formats we will probably need:
|
||||
|
||||
ARGB/ABGR with 16/32/64 bit integer/floating channels
|
||||
YUV2,
|
||||
YV12
|
||||
|
||||
Also we may need the ability to distinguish between PICT_c8 and
|
||||
PICT_x4c4. (This could be done by interpreting the A channel as
|
||||
the depth for TYPE_COLOR and TYPE_GRAY formats).
|
||||
|
||||
A possibility may be to reserve the two top bits and make them
|
||||
encode "number of places to shift the channel widths given" Since
|
||||
these bits are 00 at the moment everything will continue to work,
|
||||
but these additional widths will be allowed:
|
||||
|
||||
All even widths between 18-32
|
||||
All multiples of four widths between 33 and 64
|
||||
All multiples of eight between 64 and 128
|
||||
|
||||
This means things like r21g22b21 won't work - is that worth
|
||||
worrying about? I don't think so. And of course the bpp field
|
||||
can't handle a depth of over 256, so > 64 bit channels arent'
|
||||
really all that useful.
|
||||
|
||||
We could reserve one extra bit to indicate floating point, but
|
||||
we may also just add
|
||||
|
||||
PIXMAN_TYPE_ARGB_FLOAT
|
||||
PIXMAN_TYPE_BGRA_FLOAT
|
||||
PIXMAN_TYPE_A_FLOAT
|
||||
|
||||
image types. With five bits we can support up to 32 different
|
||||
format types, which should be enough for everybody, even if we
|
||||
decide to support all the various video formats here:
|
||||
|
||||
http://www.fourcc.org/yuv.php
|
||||
|
||||
It may make sense to have a PIXMAN_TYPE_YUV, and then use the
|
||||
channel bits to specify the exact subtype.
|
||||
|
||||
What about color spaces such a linear vs. srGB etc.?
|
||||
|
||||
|
||||
done:
|
||||
|
||||
- Run cairo test suite; fix bugs
|
||||
- one bug in source-scale-clip
|
||||
|
||||
- Remove the warning suppression in the ACCESS_MEM macro and fix the
|
||||
warnings that are real
|
||||
- irrelevant now.
|
||||
|
||||
- make the wrapper functions global instead of image specific
|
||||
- this won't work since pixman is linked to both fb and wfb
|
||||
|
||||
- Add non-mmx solid fill
|
||||
|
||||
- Make sure the endian-ness macros are defined correctly.
|
||||
|
||||
- The rectangles in a region probably shouldn't be returned const as
|
||||
the X server will be changing them.
|
||||
|
||||
- Right now we _always_ have a clip region, which is empty by default.
|
||||
Why does this work at all? It probably doesn't. The server
|
||||
distinguishes two cases, one where nothing is clipped (CT_NONE), and
|
||||
one where there is a clip region (CT_REGION).
|
||||
|
||||
- Default clip region should be the full image
|
||||
|
||||
- Test if pseudo color still works. It does, but it also shows that
|
||||
copying a pixman_indexed_t on every composite operation is not
|
||||
going to fly. So, for now set_indexed() does not copy the
|
||||
indexed table.
|
||||
|
||||
Also just the malloc() to allocate a pixman image shows up pretty
|
||||
high.
|
||||
|
||||
Options include
|
||||
|
||||
- Make all the setters not copy their arguments
|
||||
|
||||
- Possibly combined with going back to the stack allocated
|
||||
approach that we already use for regions.
|
||||
|
||||
- Keep a cached pixman_image_t around for every picture. It would
|
||||
have to be kept uptodate every time something changes about the
|
||||
picture.
|
||||
|
||||
- Break the X server ABI and simply have the relevant parameter
|
||||
stored in the pixman image. This would have the additional benefits
|
||||
that:
|
||||
|
||||
- We can get rid of the annoying repeat field which is duplicated
|
||||
elsewhere.
|
||||
|
||||
- We can use pixman_color_t and pixman_gradient_stop_t
|
||||
etc. instead of the types that are defined in
|
||||
renderproto.h
|
||||
|
||||
10
gfx/cairo/libpixman/src/Makefile.in
Normal file
10
gfx/cairo/libpixman/src/Makefile.in
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
# The ARM asm functions here don't appreciate being called by functions
|
||||
# compiled with -mapcs-frame. See bug 832752.
|
||||
CXXFLAGS := $(filter-out -mapcs-frame,$(CXXFLAGS))
|
||||
CFLAGS := $(filter-out -mapcs-frame,$(CFLAGS))
|
||||
86
gfx/cairo/libpixman/src/make-combine.pl
Normal file
86
gfx/cairo/libpixman/src/make-combine.pl
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
$usage = "Usage: combine.pl { 8 | 16 } < pixman-combine.c.template";
|
||||
|
||||
$#ARGV == 0 or die $usage;
|
||||
|
||||
# Get the component size.
|
||||
$size = int($ARGV[0]);
|
||||
$size == 8 or $size == 16 or die $usage;
|
||||
|
||||
$pixel_size = $size * 4;
|
||||
$half_pixel_size = $size * 2;
|
||||
|
||||
sub mask {
|
||||
my $str = shift;
|
||||
my $suffix;
|
||||
$suffix = "ULL" if $size > 8;
|
||||
|
||||
return "0x" . $str . $suffix;
|
||||
}
|
||||
|
||||
# Generate mask strings.
|
||||
$nibbles = $size / 4;
|
||||
$mask = "f" x $nibbles;
|
||||
$zero_mask = "0" x $nibbles;
|
||||
$one_half = "8" . "0" x ($nibbles - 1);
|
||||
|
||||
print "/* WARNING: This file is generated by combine.pl from combine.inc.\n";
|
||||
print " Please edit one of those files rather than this one. */\n";
|
||||
print "\n";
|
||||
|
||||
print "#line 1 \"pixman-combine.c.template\"\n";
|
||||
|
||||
$mask_ = mask($mask);
|
||||
$one_half_ = mask($one_half);
|
||||
$g_mask = mask($mask . $zero_mask);
|
||||
$b_mask = mask($mask . $zero_mask x 2);
|
||||
$a_mask = mask($mask . $zero_mask x 3);
|
||||
$rb_mask = mask($mask . $zero_mask . $mask);
|
||||
$ag_mask = mask($mask . $zero_mask . $mask . $zero_mask);
|
||||
$rb_one_half = mask($one_half . $zero_mask . $one_half);
|
||||
$rb_mask_plus_one = mask("1" . $zero_mask x 2 . "1" . $zero_mask);
|
||||
|
||||
while (<STDIN>) {
|
||||
# Mask and 1/2 value for a single component.
|
||||
s/#define COMPONENT_SIZE\b/$& $size/;
|
||||
s/#define MASK\b/$& $mask_/;
|
||||
s/#define ONE_HALF\b/$& $one_half_/;
|
||||
|
||||
# Shifts and masks for green, blue, and alpha.
|
||||
s/#define G_SHIFT\b/$& $size/;
|
||||
s/#define R_SHIFT\b/$& $size * 2/;
|
||||
s/#define A_SHIFT\b/$& $size * 3/;
|
||||
s/#define G_MASK\b/$& $g_mask/;
|
||||
s/#define R_MASK\b/$& $b_mask/;
|
||||
s/#define A_MASK\b/$& $a_mask/;
|
||||
|
||||
# Special values for dealing with red + blue at the same time.
|
||||
s/#define RB_MASK\b/$& $rb_mask/;
|
||||
s/#define AG_MASK\b/$& $ag_mask/;
|
||||
s/#define RB_ONE_HALF\b/$& $rb_one_half/;
|
||||
s/#define RB_MASK_PLUS_ONE\b/$& $rb_mask_plus_one/;
|
||||
|
||||
# Add 32/64 suffix to combining function types.
|
||||
s/\bCombineFunc\b/CombineFunc$pixel_size/;
|
||||
s/\bFbComposeFunctions\b/FbComposeFunctions$pixel_size/;
|
||||
s/combine_width/combine_$pixel_size/;
|
||||
s/_pixman_setup_combiner_functions_width/_pixman_setup_combiner_functions_$pixel_size/;
|
||||
s/UNc/UN$size/g;
|
||||
s/ALPHA_c/ALPHA_$size/g;
|
||||
s/RED_c/RED_$size/g;
|
||||
s/GREEN_c/GREEN_$size/g;
|
||||
s/BLUE_c/BLUE_$size/g;
|
||||
|
||||
# Convert comp*_t values into the appropriate real types.
|
||||
s/comp1_t/uint${size}_t/g;
|
||||
s/comp2_t/uint${half_pixel_size}_t/g;
|
||||
s/comp4_t/uint${pixel_size}_t/g;
|
||||
|
||||
# Change the function table name for the 64-bit version.
|
||||
s/pixman_composeFunctions/pixman_composeFunctions64/ if $size == 16;
|
||||
|
||||
# Change the header for the 64-bit version
|
||||
s/pixman-combine.h/pixman-combine64.h/ if $size == 16;
|
||||
s/pixman-combine.h/pixman-combine32.h/ if $size == 8;
|
||||
|
||||
print;
|
||||
}
|
||||
163
gfx/cairo/libpixman/src/moz.build
Normal file
163
gfx/cairo/libpixman/src/moz.build
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
EXPORTS += [
|
||||
'pixman-version.h',
|
||||
'pixman.h',
|
||||
]
|
||||
|
||||
# Apple's arm assembler doesn't support the same syntax as
|
||||
# the standard GNU assembler, so use the C fallback paths for now.
|
||||
# This may be fixable if clang's ARM/iOS assembler improves into a
|
||||
# viable solution in the future.
|
||||
if CONFIG['OS_ARCH'] != 'Darwin' and CONFIG['GNU_CC']:
|
||||
if CONFIG['HAVE_ARM_NEON']:
|
||||
SOURCES += [
|
||||
'pixman-arm-neon-asm-bilinear.S',
|
||||
'pixman-arm-neon-asm.S',
|
||||
]
|
||||
if CONFIG['HAVE_ARM_SIMD']:
|
||||
SOURCES += [
|
||||
'pixman-arm-simd-asm-scaled.S',
|
||||
'pixman-arm-simd-asm.S',
|
||||
]
|
||||
if CONFIG['CLANG_CXX']:
|
||||
ASFLAGS += [
|
||||
'-no-integrated-as',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'pixman-access-accessors.c',
|
||||
'pixman-access.c',
|
||||
'pixman-arm.c',
|
||||
'pixman-bits-image.c',
|
||||
'pixman-combine-float.c',
|
||||
'pixman-combine16.c',
|
||||
'pixman-combine32.c',
|
||||
'pixman-conical-gradient.c',
|
||||
'pixman-edge-accessors.c',
|
||||
'pixman-edge.c',
|
||||
'pixman-fast-path.c',
|
||||
'pixman-filter.c',
|
||||
'pixman-general.c',
|
||||
'pixman-glyph.c',
|
||||
'pixman-gradient-walker.c',
|
||||
'pixman-image.c',
|
||||
'pixman-implementation.c',
|
||||
'pixman-linear-gradient.c',
|
||||
'pixman-matrix.c',
|
||||
'pixman-mips.c',
|
||||
'pixman-noop.c',
|
||||
'pixman-ppc.c',
|
||||
'pixman-radial-gradient.c',
|
||||
'pixman-region16.c',
|
||||
'pixman-region32.c',
|
||||
'pixman-solid-fill.c',
|
||||
'pixman-trap.c',
|
||||
'pixman-utils.c',
|
||||
'pixman-x86.c',
|
||||
'pixman.c',
|
||||
]
|
||||
|
||||
# We allow warnings for third-party code that can be updated from upstream.
|
||||
ALLOW_COMPILER_WARNINGS = True
|
||||
|
||||
FINAL_LIBRARY = 'gkmedias'
|
||||
LOCAL_INCLUDES += [
|
||||
'../../cairo/src',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_USE_PTHREADS']:
|
||||
DEFINES['HAVE_PTHREAD_SETSPECIFIC'] = True
|
||||
|
||||
if CONFIG['_MSC_VER']:
|
||||
DEFINES['PIXMAN_USE_XP_DLL_TLS_WORKAROUND'] = True
|
||||
|
||||
DEFINES['PACKAGE'] = 'mozpixman'
|
||||
|
||||
DEFINES['_USE_MATH_DEFINES'] = True
|
||||
|
||||
use_mmx = False
|
||||
use_sse2 = False
|
||||
use_vmx = False
|
||||
use_arm_simd_gcc = False
|
||||
use_arm_neon_gcc = False
|
||||
if '86' in CONFIG['OS_TEST']:
|
||||
use_sse2 = True
|
||||
if '64' not in CONFIG['OS_TEST']:
|
||||
if CONFIG['_MSC_VER']:
|
||||
use_mmx = True
|
||||
if CONFIG['GNU_CC']:
|
||||
use_mmx = True
|
||||
elif 'ppc' in CONFIG['OS_TEST']:
|
||||
if CONFIG['GNU_CC']:
|
||||
use_vmx = True
|
||||
# Apple's arm assembler doesn't support the same syntax as
|
||||
# the standard GNU assembler, so use the C fallback paths for now.
|
||||
# This may be fixable if clang's ARM/iOS assembler improves into a
|
||||
# viable solution in the future.
|
||||
elif 'arm' in CONFIG['OS_TEST']:
|
||||
if CONFIG['OS_ARCH'] != 'Darwin':
|
||||
if CONFIG['HAVE_ARM_SIMD']:
|
||||
use_arm_simd_gcc = True
|
||||
if CONFIG['HAVE_ARM_NEON']:
|
||||
use_arm_neon_gcc = True
|
||||
|
||||
if use_mmx:
|
||||
DEFINES['USE_MMX'] = True
|
||||
SOURCES += ['pixman-mmx.c']
|
||||
SOURCES['pixman-mmx.c'].flags += CONFIG['MMX_FLAGS']
|
||||
if CONFIG['GNU_CC']:
|
||||
SOURCES['pixman-mmx.c'].flags += [
|
||||
'-Winline',
|
||||
'--param inline-unit-growth=10000',
|
||||
'--param large-function-growth=10000',
|
||||
]
|
||||
|
||||
if use_sse2:
|
||||
DEFINES['USE_SSE'] = True
|
||||
DEFINES['USE_SSE2'] = True
|
||||
SOURCES += ['pixman-sse2.c']
|
||||
SOURCES['pixman-sse2.c'].flags += CONFIG['SSE_FLAGS'] + CONFIG['SSE2_FLAGS']
|
||||
if CONFIG['GNU_CC']:
|
||||
SOURCES['pixman-sse2.c'].flags += ['-Winline']
|
||||
|
||||
if use_vmx:
|
||||
DEFINES['USE_VMX'] = True
|
||||
SOURCES += ['pixman-vmx.c']
|
||||
SOURCES['pixman-vmx.c'].flags += ['-maltivec']
|
||||
|
||||
if use_arm_simd_gcc:
|
||||
DEFINES['USE_ARM_SIMD'] = True
|
||||
SOURCES += ['pixman-arm-simd.c']
|
||||
|
||||
if use_arm_neon_gcc:
|
||||
DEFINES['USE_ARM_NEON'] = True
|
||||
SOURCES += ['pixman-arm-neon.c']
|
||||
SOURCES['pixman-arm-neon.c'].flags += CONFIG['NEON_FLAGS']
|
||||
|
||||
# Suppress warnings in third-party code.
|
||||
if CONFIG['GNU_CC'] or CONFIG['CLANG_CL']:
|
||||
CFLAGS += [
|
||||
'-Wno-address',
|
||||
'-Wno-missing-field-initializers',
|
||||
'-Wno-sign-compare',
|
||||
'-Wno-unused', # too many unused warnings; ignore
|
||||
]
|
||||
if CONFIG['CLANG_CXX'] or CONFIG['CLANG_CL']:
|
||||
CFLAGS += [
|
||||
'-Wno-incompatible-pointer-types',
|
||||
'-Wno-tautological-compare',
|
||||
'-Wno-tautological-constant-out-of-range-compare',
|
||||
]
|
||||
if CONFIG['CLANG_CL']:
|
||||
CFLAGS += [
|
||||
'-Wno-unused-variable',
|
||||
]
|
||||
|
||||
# See bug 386897.
|
||||
if CONFIG['OS_TARGET'] == 'Android' and CONFIG['MOZ_OPTIMIZE']:
|
||||
CFLAGS += ['-O2']
|
||||
3
gfx/cairo/libpixman/src/pixman-access-accessors.c
Normal file
3
gfx/cairo/libpixman/src/pixman-access-accessors.c
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#define PIXMAN_FB_ACCESSORS
|
||||
|
||||
#include "pixman-access.c"
|
||||
1492
gfx/cairo/libpixman/src/pixman-access.c
Normal file
1492
gfx/cairo/libpixman/src/pixman-access.c
Normal file
File diff suppressed because it is too large
Load diff
25
gfx/cairo/libpixman/src/pixman-accessor.h
Normal file
25
gfx/cairo/libpixman/src/pixman-accessor.h
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#ifdef PIXMAN_FB_ACCESSORS
|
||||
|
||||
#define READ(img, ptr) \
|
||||
(((bits_image_t *)(img))->read_func ((ptr), sizeof(*(ptr))))
|
||||
#define WRITE(img, ptr,val) \
|
||||
(((bits_image_t *)(img))->write_func ((ptr), (val), sizeof (*(ptr))))
|
||||
|
||||
#define MEMSET_WRAPPED(img, dst, val, size) \
|
||||
do { \
|
||||
size_t _i; \
|
||||
uint8_t *_dst = (uint8_t*)(dst); \
|
||||
for(_i = 0; _i < (size_t) size; _i++) { \
|
||||
WRITE((img), _dst +_i, (val)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define READ(img, ptr) (*(ptr))
|
||||
#define WRITE(img, ptr, val) (*(ptr) = (val))
|
||||
#define MEMSET_WRAPPED(img, dst, val, size) \
|
||||
memset(dst, val, size)
|
||||
|
||||
#endif
|
||||
|
||||
428
gfx/cairo/libpixman/src/pixman-arm-common.h
Normal file
428
gfx/cairo/libpixman/src/pixman-arm-common.h
Normal file
|
|
@ -0,0 +1,428 @@
|
|||
/*
|
||||
* Copyright © 2010 Nokia Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Author: Siarhei Siamashka (siarhei.siamashka@nokia.com)
|
||||
*/
|
||||
|
||||
#ifndef PIXMAN_ARM_COMMON_H
|
||||
#define PIXMAN_ARM_COMMON_H
|
||||
|
||||
#include "pixman-inlines.h"
|
||||
|
||||
/* Define some macros which can expand into proxy functions between
|
||||
* ARM assembly optimized functions and the rest of pixman fast path API.
|
||||
*
|
||||
* All the low level ARM assembly functions have to use ARM EABI
|
||||
* calling convention and take up to 8 arguments:
|
||||
* width, height, dst, dst_stride, src, src_stride, mask, mask_stride
|
||||
*
|
||||
* The arguments are ordered with the most important coming first (the
|
||||
* first 4 arguments are passed to function in registers, the rest are
|
||||
* on stack). The last arguments are optional, for example if the
|
||||
* function is not using mask, then 'mask' and 'mask_stride' can be
|
||||
* omitted when doing a function call.
|
||||
*
|
||||
* Arguments 'src' and 'mask' contain either a pointer to the top left
|
||||
* pixel of the composited rectangle or a pixel color value depending
|
||||
* on the function type. In the case of just a color value (solid source
|
||||
* or mask), the corresponding stride argument is unused.
|
||||
*/
|
||||
|
||||
#define SKIP_ZERO_SRC 1
|
||||
#define SKIP_ZERO_MASK 2
|
||||
|
||||
#define PIXMAN_ARM_BIND_FAST_PATH_SRC_DST(cputype, name, \
|
||||
src_type, src_cnt, \
|
||||
dst_type, dst_cnt) \
|
||||
void \
|
||||
pixman_composite_##name##_asm_##cputype (int32_t w, \
|
||||
int32_t h, \
|
||||
dst_type *dst, \
|
||||
int32_t dst_stride, \
|
||||
src_type *src, \
|
||||
int32_t src_stride); \
|
||||
\
|
||||
static void \
|
||||
cputype##_composite_##name (pixman_implementation_t *imp, \
|
||||
pixman_composite_info_t *info) \
|
||||
{ \
|
||||
PIXMAN_COMPOSITE_ARGS (info); \
|
||||
dst_type *dst_line; \
|
||||
src_type *src_line; \
|
||||
int32_t dst_stride, src_stride; \
|
||||
\
|
||||
PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, src_type, \
|
||||
src_stride, src_line, src_cnt); \
|
||||
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
|
||||
dst_stride, dst_line, dst_cnt); \
|
||||
\
|
||||
pixman_composite_##name##_asm_##cputype (width, height, \
|
||||
dst_line, dst_stride, \
|
||||
src_line, src_stride); \
|
||||
}
|
||||
|
||||
#define PIXMAN_ARM_BIND_FAST_PATH_N_DST(flags, cputype, name, \
|
||||
dst_type, dst_cnt) \
|
||||
void \
|
||||
pixman_composite_##name##_asm_##cputype (int32_t w, \
|
||||
int32_t h, \
|
||||
dst_type *dst, \
|
||||
int32_t dst_stride, \
|
||||
uint32_t src); \
|
||||
\
|
||||
static void \
|
||||
cputype##_composite_##name (pixman_implementation_t *imp, \
|
||||
pixman_composite_info_t *info) \
|
||||
{ \
|
||||
PIXMAN_COMPOSITE_ARGS (info); \
|
||||
dst_type *dst_line; \
|
||||
int32_t dst_stride; \
|
||||
uint32_t src; \
|
||||
\
|
||||
src = _pixman_image_get_solid ( \
|
||||
imp, src_image, dest_image->bits.format); \
|
||||
\
|
||||
if ((flags & SKIP_ZERO_SRC) && src == 0) \
|
||||
return; \
|
||||
\
|
||||
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
|
||||
dst_stride, dst_line, dst_cnt); \
|
||||
\
|
||||
pixman_composite_##name##_asm_##cputype (width, height, \
|
||||
dst_line, dst_stride, \
|
||||
src); \
|
||||
}
|
||||
|
||||
#define PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST(flags, cputype, name, \
|
||||
mask_type, mask_cnt, \
|
||||
dst_type, dst_cnt) \
|
||||
void \
|
||||
pixman_composite_##name##_asm_##cputype (int32_t w, \
|
||||
int32_t h, \
|
||||
dst_type *dst, \
|
||||
int32_t dst_stride, \
|
||||
uint32_t src, \
|
||||
int32_t unused, \
|
||||
mask_type *mask, \
|
||||
int32_t mask_stride); \
|
||||
\
|
||||
static void \
|
||||
cputype##_composite_##name (pixman_implementation_t *imp, \
|
||||
pixman_composite_info_t *info) \
|
||||
{ \
|
||||
PIXMAN_COMPOSITE_ARGS (info); \
|
||||
dst_type *dst_line; \
|
||||
mask_type *mask_line; \
|
||||
int32_t dst_stride, mask_stride; \
|
||||
uint32_t src; \
|
||||
\
|
||||
src = _pixman_image_get_solid ( \
|
||||
imp, src_image, dest_image->bits.format); \
|
||||
\
|
||||
if ((flags & SKIP_ZERO_SRC) && src == 0) \
|
||||
return; \
|
||||
\
|
||||
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
|
||||
dst_stride, dst_line, dst_cnt); \
|
||||
PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type, \
|
||||
mask_stride, mask_line, mask_cnt); \
|
||||
\
|
||||
pixman_composite_##name##_asm_##cputype (width, height, \
|
||||
dst_line, dst_stride, \
|
||||
src, 0, \
|
||||
mask_line, mask_stride); \
|
||||
}
|
||||
|
||||
#define PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST(flags, cputype, name, \
|
||||
src_type, src_cnt, \
|
||||
dst_type, dst_cnt) \
|
||||
void \
|
||||
pixman_composite_##name##_asm_##cputype (int32_t w, \
|
||||
int32_t h, \
|
||||
dst_type *dst, \
|
||||
int32_t dst_stride, \
|
||||
src_type *src, \
|
||||
int32_t src_stride, \
|
||||
uint32_t mask); \
|
||||
\
|
||||
static void \
|
||||
cputype##_composite_##name (pixman_implementation_t *imp, \
|
||||
pixman_composite_info_t *info) \
|
||||
{ \
|
||||
PIXMAN_COMPOSITE_ARGS (info); \
|
||||
dst_type *dst_line; \
|
||||
src_type *src_line; \
|
||||
int32_t dst_stride, src_stride; \
|
||||
uint32_t mask; \
|
||||
\
|
||||
mask = _pixman_image_get_solid ( \
|
||||
imp, mask_image, dest_image->bits.format); \
|
||||
\
|
||||
if ((flags & SKIP_ZERO_MASK) && mask == 0) \
|
||||
return; \
|
||||
\
|
||||
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
|
||||
dst_stride, dst_line, dst_cnt); \
|
||||
PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, src_type, \
|
||||
src_stride, src_line, src_cnt); \
|
||||
\
|
||||
pixman_composite_##name##_asm_##cputype (width, height, \
|
||||
dst_line, dst_stride, \
|
||||
src_line, src_stride, \
|
||||
mask); \
|
||||
}
|
||||
|
||||
#define PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST(cputype, name, \
|
||||
src_type, src_cnt, \
|
||||
mask_type, mask_cnt, \
|
||||
dst_type, dst_cnt) \
|
||||
void \
|
||||
pixman_composite_##name##_asm_##cputype (int32_t w, \
|
||||
int32_t h, \
|
||||
dst_type *dst, \
|
||||
int32_t dst_stride, \
|
||||
src_type *src, \
|
||||
int32_t src_stride, \
|
||||
mask_type *mask, \
|
||||
int32_t mask_stride); \
|
||||
\
|
||||
static void \
|
||||
cputype##_composite_##name (pixman_implementation_t *imp, \
|
||||
pixman_composite_info_t *info) \
|
||||
{ \
|
||||
PIXMAN_COMPOSITE_ARGS (info); \
|
||||
dst_type *dst_line; \
|
||||
src_type *src_line; \
|
||||
mask_type *mask_line; \
|
||||
int32_t dst_stride, src_stride, mask_stride; \
|
||||
\
|
||||
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
|
||||
dst_stride, dst_line, dst_cnt); \
|
||||
PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, src_type, \
|
||||
src_stride, src_line, src_cnt); \
|
||||
PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type, \
|
||||
mask_stride, mask_line, mask_cnt); \
|
||||
\
|
||||
pixman_composite_##name##_asm_##cputype (width, height, \
|
||||
dst_line, dst_stride, \
|
||||
src_line, src_stride, \
|
||||
mask_line, mask_stride); \
|
||||
}
|
||||
|
||||
#define PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST(cputype, name, op, \
|
||||
src_type, dst_type) \
|
||||
void \
|
||||
pixman_scaled_nearest_scanline_##name##_##op##_asm_##cputype ( \
|
||||
int32_t w, \
|
||||
dst_type * dst, \
|
||||
const src_type * src, \
|
||||
pixman_fixed_t vx, \
|
||||
pixman_fixed_t unit_x, \
|
||||
pixman_fixed_t max_vx); \
|
||||
\
|
||||
static force_inline void \
|
||||
scaled_nearest_scanline_##cputype##_##name##_##op (dst_type * pd, \
|
||||
const src_type * ps, \
|
||||
int32_t w, \
|
||||
pixman_fixed_t vx, \
|
||||
pixman_fixed_t unit_x, \
|
||||
pixman_fixed_t max_vx, \
|
||||
pixman_bool_t zero_src) \
|
||||
{ \
|
||||
pixman_scaled_nearest_scanline_##name##_##op##_asm_##cputype (w, pd, ps, \
|
||||
vx, unit_x, \
|
||||
max_vx); \
|
||||
} \
|
||||
\
|
||||
FAST_NEAREST_MAINLOOP (cputype##_##name##_cover_##op, \
|
||||
scaled_nearest_scanline_##cputype##_##name##_##op, \
|
||||
src_type, dst_type, COVER) \
|
||||
FAST_NEAREST_MAINLOOP (cputype##_##name##_none_##op, \
|
||||
scaled_nearest_scanline_##cputype##_##name##_##op, \
|
||||
src_type, dst_type, NONE) \
|
||||
FAST_NEAREST_MAINLOOP (cputype##_##name##_pad_##op, \
|
||||
scaled_nearest_scanline_##cputype##_##name##_##op, \
|
||||
src_type, dst_type, PAD) \
|
||||
FAST_NEAREST_MAINLOOP (cputype##_##name##_normal_##op, \
|
||||
scaled_nearest_scanline_##cputype##_##name##_##op, \
|
||||
src_type, dst_type, NORMAL)
|
||||
|
||||
/* Provide entries for the fast path table */
|
||||
#define PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH(op,s,d,func) \
|
||||
SIMPLE_NEAREST_FAST_PATH_COVER (op,s,d,func), \
|
||||
SIMPLE_NEAREST_FAST_PATH_NONE (op,s,d,func), \
|
||||
SIMPLE_NEAREST_FAST_PATH_PAD (op,s,d,func), \
|
||||
SIMPLE_NEAREST_FAST_PATH_NORMAL (op,s,d,func)
|
||||
|
||||
#define PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_A8_DST(flags, cputype, name, op, \
|
||||
src_type, dst_type) \
|
||||
void \
|
||||
pixman_scaled_nearest_scanline_##name##_##op##_asm_##cputype ( \
|
||||
int32_t w, \
|
||||
dst_type * dst, \
|
||||
const src_type * src, \
|
||||
pixman_fixed_t vx, \
|
||||
pixman_fixed_t unit_x, \
|
||||
pixman_fixed_t max_vx, \
|
||||
const uint8_t * mask); \
|
||||
\
|
||||
static force_inline void \
|
||||
scaled_nearest_scanline_##cputype##_##name##_##op (const uint8_t * mask, \
|
||||
dst_type * pd, \
|
||||
const src_type * ps, \
|
||||
int32_t w, \
|
||||
pixman_fixed_t vx, \
|
||||
pixman_fixed_t unit_x, \
|
||||
pixman_fixed_t max_vx, \
|
||||
pixman_bool_t zero_src) \
|
||||
{ \
|
||||
if ((flags & SKIP_ZERO_SRC) && zero_src) \
|
||||
return; \
|
||||
pixman_scaled_nearest_scanline_##name##_##op##_asm_##cputype (w, pd, ps, \
|
||||
vx, unit_x, \
|
||||
max_vx, \
|
||||
mask); \
|
||||
} \
|
||||
\
|
||||
FAST_NEAREST_MAINLOOP_COMMON (cputype##_##name##_cover_##op, \
|
||||
scaled_nearest_scanline_##cputype##_##name##_##op,\
|
||||
src_type, uint8_t, dst_type, COVER, TRUE, FALSE)\
|
||||
FAST_NEAREST_MAINLOOP_COMMON (cputype##_##name##_none_##op, \
|
||||
scaled_nearest_scanline_##cputype##_##name##_##op,\
|
||||
src_type, uint8_t, dst_type, NONE, TRUE, FALSE) \
|
||||
FAST_NEAREST_MAINLOOP_COMMON (cputype##_##name##_pad_##op, \
|
||||
scaled_nearest_scanline_##cputype##_##name##_##op,\
|
||||
src_type, uint8_t, dst_type, PAD, TRUE, FALSE) \
|
||||
FAST_NEAREST_MAINLOOP_COMMON (cputype##_##name##_normal_##op, \
|
||||
scaled_nearest_scanline_##cputype##_##name##_##op,\
|
||||
src_type, uint8_t, dst_type, NORMAL, TRUE, FALSE)
|
||||
|
||||
/* Provide entries for the fast path table */
|
||||
#define PIXMAN_ARM_SIMPLE_NEAREST_A8_MASK_FAST_PATH(op,s,d,func) \
|
||||
SIMPLE_NEAREST_A8_MASK_FAST_PATH_COVER (op,s,d,func), \
|
||||
SIMPLE_NEAREST_A8_MASK_FAST_PATH_NONE (op,s,d,func), \
|
||||
SIMPLE_NEAREST_A8_MASK_FAST_PATH_PAD (op,s,d,func), \
|
||||
SIMPLE_NEAREST_A8_MASK_FAST_PATH_NORMAL (op,s,d,func)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_DST(flags, cputype, name, op, \
|
||||
src_type, dst_type) \
|
||||
void \
|
||||
pixman_scaled_bilinear_scanline_##name##_##op##_asm_##cputype ( \
|
||||
dst_type * dst, \
|
||||
const src_type * top, \
|
||||
const src_type * bottom, \
|
||||
int wt, \
|
||||
int wb, \
|
||||
pixman_fixed_t x, \
|
||||
pixman_fixed_t ux, \
|
||||
int width); \
|
||||
\
|
||||
static force_inline void \
|
||||
scaled_bilinear_scanline_##cputype##_##name##_##op ( \
|
||||
dst_type * dst, \
|
||||
const uint32_t * mask, \
|
||||
const src_type * src_top, \
|
||||
const src_type * src_bottom, \
|
||||
int32_t w, \
|
||||
int wt, \
|
||||
int wb, \
|
||||
pixman_fixed_t vx, \
|
||||
pixman_fixed_t unit_x, \
|
||||
pixman_fixed_t max_vx, \
|
||||
pixman_bool_t zero_src) \
|
||||
{ \
|
||||
if ((flags & SKIP_ZERO_SRC) && zero_src) \
|
||||
return; \
|
||||
pixman_scaled_bilinear_scanline_##name##_##op##_asm_##cputype ( \
|
||||
dst, src_top, src_bottom, wt, wb, vx, unit_x, w); \
|
||||
} \
|
||||
\
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_cover_##op, \
|
||||
scaled_bilinear_scanline_##cputype##_##name##_##op, \
|
||||
NULL, src_type, uint32_t, dst_type, COVER, FLAG_NONE) \
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_none_##op, \
|
||||
scaled_bilinear_scanline_##cputype##_##name##_##op, \
|
||||
NULL, src_type, uint32_t, dst_type, NONE, FLAG_NONE) \
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_pad_##op, \
|
||||
scaled_bilinear_scanline_##cputype##_##name##_##op, \
|
||||
NULL, src_type, uint32_t, dst_type, PAD, FLAG_NONE) \
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_normal_##op, \
|
||||
scaled_bilinear_scanline_##cputype##_##name##_##op, \
|
||||
NULL, src_type, uint32_t, dst_type, NORMAL, \
|
||||
FLAG_NONE)
|
||||
|
||||
|
||||
#define PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_A8_DST(flags, cputype, name, op, \
|
||||
src_type, dst_type) \
|
||||
void \
|
||||
pixman_scaled_bilinear_scanline_##name##_##op##_asm_##cputype ( \
|
||||
dst_type * dst, \
|
||||
const uint8_t * mask, \
|
||||
const src_type * top, \
|
||||
const src_type * bottom, \
|
||||
int wt, \
|
||||
int wb, \
|
||||
pixman_fixed_t x, \
|
||||
pixman_fixed_t ux, \
|
||||
int width); \
|
||||
\
|
||||
static force_inline void \
|
||||
scaled_bilinear_scanline_##cputype##_##name##_##op ( \
|
||||
dst_type * dst, \
|
||||
const uint8_t * mask, \
|
||||
const src_type * src_top, \
|
||||
const src_type * src_bottom, \
|
||||
int32_t w, \
|
||||
int wt, \
|
||||
int wb, \
|
||||
pixman_fixed_t vx, \
|
||||
pixman_fixed_t unit_x, \
|
||||
pixman_fixed_t max_vx, \
|
||||
pixman_bool_t zero_src) \
|
||||
{ \
|
||||
if ((flags & SKIP_ZERO_SRC) && zero_src) \
|
||||
return; \
|
||||
pixman_scaled_bilinear_scanline_##name##_##op##_asm_##cputype ( \
|
||||
dst, mask, src_top, src_bottom, wt, wb, vx, unit_x, w); \
|
||||
} \
|
||||
\
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_cover_##op, \
|
||||
scaled_bilinear_scanline_##cputype##_##name##_##op, \
|
||||
NULL, src_type, uint8_t, dst_type, COVER, \
|
||||
FLAG_HAVE_NON_SOLID_MASK) \
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_none_##op, \
|
||||
scaled_bilinear_scanline_##cputype##_##name##_##op, \
|
||||
NULL, src_type, uint8_t, dst_type, NONE, \
|
||||
FLAG_HAVE_NON_SOLID_MASK) \
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_pad_##op, \
|
||||
scaled_bilinear_scanline_##cputype##_##name##_##op, \
|
||||
NULL, src_type, uint8_t, dst_type, PAD, \
|
||||
FLAG_HAVE_NON_SOLID_MASK) \
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_normal_##op, \
|
||||
scaled_bilinear_scanline_##cputype##_##name##_##op, \
|
||||
NULL, src_type, uint8_t, dst_type, NORMAL, \
|
||||
FLAG_HAVE_NON_SOLID_MASK)
|
||||
|
||||
|
||||
#endif
|
||||
21
gfx/cairo/libpixman/src/pixman-arm-detect-win32.asm
Normal file
21
gfx/cairo/libpixman/src/pixman-arm-detect-win32.asm
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
area pixman_msvc, code, readonly
|
||||
|
||||
export pixman_msvc_try_arm_simd_op
|
||||
|
||||
pixman_msvc_try_arm_simd_op
|
||||
;; I don't think the msvc arm asm knows how to do SIMD insns
|
||||
;; uqadd8 r3,r3,r3
|
||||
dcd 0xe6633f93
|
||||
mov pc,lr
|
||||
endp
|
||||
|
||||
export pixman_msvc_try_arm_neon_op
|
||||
|
||||
pixman_msvc_try_arm_neon_op
|
||||
;; I don't think the msvc arm asm knows how to do NEON insns
|
||||
;; veor d0,d0,d0
|
||||
dcd 0xf3000110
|
||||
mov pc,lr
|
||||
endp
|
||||
|
||||
end
|
||||
1368
gfx/cairo/libpixman/src/pixman-arm-neon-asm-bilinear.S
Normal file
1368
gfx/cairo/libpixman/src/pixman-arm-neon-asm-bilinear.S
Normal file
File diff suppressed because it is too large
Load diff
3650
gfx/cairo/libpixman/src/pixman-arm-neon-asm.S
Normal file
3650
gfx/cairo/libpixman/src/pixman-arm-neon-asm.S
Normal file
File diff suppressed because it is too large
Load diff
1204
gfx/cairo/libpixman/src/pixman-arm-neon-asm.h
Normal file
1204
gfx/cairo/libpixman/src/pixman-arm-neon-asm.h
Normal file
File diff suppressed because it is too large
Load diff
513
gfx/cairo/libpixman/src/pixman-arm-neon.c
Normal file
513
gfx/cairo/libpixman/src/pixman-arm-neon.c
Normal file
|
|
@ -0,0 +1,513 @@
|
|||
/*
|
||||
* Copyright © 2009 ARM Ltd, Movial Creative Technologies Oy
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of ARM Ltd not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. ARM Ltd makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Author: Ian Rickards (ian.rickards@arm.com)
|
||||
* Author: Jonathan Morton (jonathan.morton@movial.com)
|
||||
* Author: Markku Vire (markku.vire@movial.com)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include "pixman-private.h"
|
||||
#include "pixman-arm-common.h"
|
||||
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_8888_8888,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_x888_8888,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_0565_0565,
|
||||
uint16_t, 1, uint16_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_0888_0888,
|
||||
uint8_t, 3, uint8_t, 3)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_8888_0565,
|
||||
uint32_t, 1, uint16_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_0565_8888,
|
||||
uint16_t, 1, uint32_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_0888_8888_rev,
|
||||
uint8_t, 3, uint32_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_0888_0565_rev,
|
||||
uint8_t, 3, uint16_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_pixbuf_8888,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_rpixbuf_8888,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, add_8_8,
|
||||
uint8_t, 1, uint8_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, add_8888_8888,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, over_8888_0565,
|
||||
uint32_t, 1, uint16_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, over_8888_8888,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, out_reverse_8_0565,
|
||||
uint8_t, 1, uint16_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, out_reverse_8_8888,
|
||||
uint8_t, 1, uint32_t, 1)
|
||||
|
||||
PIXMAN_ARM_BIND_FAST_PATH_N_DST (SKIP_ZERO_SRC, neon, over_n_0565,
|
||||
uint16_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_N_DST (SKIP_ZERO_SRC, neon, over_n_8888,
|
||||
uint32_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_N_DST (SKIP_ZERO_SRC, neon, over_reverse_n_8888,
|
||||
uint32_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_N_DST (0, neon, in_n_8,
|
||||
uint8_t, 1)
|
||||
|
||||
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, over_n_8_0565,
|
||||
uint8_t, 1, uint16_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, over_n_8_8888,
|
||||
uint8_t, 1, uint32_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, over_n_8888_8888_ca,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, over_n_8888_0565_ca,
|
||||
uint32_t, 1, uint16_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, over_n_8_8,
|
||||
uint8_t, 1, uint8_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, add_n_8_8,
|
||||
uint8_t, 1, uint8_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, add_n_8_8888,
|
||||
uint8_t, 1, uint32_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (0, neon, src_n_8_8888,
|
||||
uint8_t, 1, uint32_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (0, neon, src_n_8_8,
|
||||
uint8_t, 1, uint8_t, 1)
|
||||
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, neon, over_8888_n_8888,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, neon, over_8888_n_0565,
|
||||
uint32_t, 1, uint16_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, neon, over_0565_n_0565,
|
||||
uint16_t, 1, uint16_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, neon, add_8888_n_8888,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, add_8_8_8,
|
||||
uint8_t, 1, uint8_t, 1, uint8_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, add_0565_8_0565,
|
||||
uint16_t, 1, uint8_t, 1, uint16_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, add_8888_8_8888,
|
||||
uint32_t, 1, uint8_t, 1, uint32_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, add_8888_8888_8888,
|
||||
uint32_t, 1, uint32_t, 1, uint32_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, over_8888_8_8888,
|
||||
uint32_t, 1, uint8_t, 1, uint32_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, over_8888_8888_8888,
|
||||
uint32_t, 1, uint32_t, 1, uint32_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, over_8888_8_0565,
|
||||
uint32_t, 1, uint8_t, 1, uint16_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, over_0565_8_0565,
|
||||
uint16_t, 1, uint8_t, 1, uint16_t, 1)
|
||||
|
||||
PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST (neon, 8888_8888, OVER,
|
||||
uint32_t, uint32_t)
|
||||
PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST (neon, 8888_0565, OVER,
|
||||
uint32_t, uint16_t)
|
||||
PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST (neon, 8888_0565, SRC,
|
||||
uint32_t, uint16_t)
|
||||
PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST (neon, 0565_8888, SRC,
|
||||
uint16_t, uint32_t)
|
||||
|
||||
PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_A8_DST (SKIP_ZERO_SRC, neon, 8888_8_0565,
|
||||
OVER, uint32_t, uint16_t)
|
||||
PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_A8_DST (SKIP_ZERO_SRC, neon, 0565_8_0565,
|
||||
OVER, uint16_t, uint16_t)
|
||||
|
||||
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_DST (0, neon, 8888_8888, SRC,
|
||||
uint32_t, uint32_t)
|
||||
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_DST (0, neon, 8888_0565, SRC,
|
||||
uint32_t, uint16_t)
|
||||
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_DST (0, neon, 0565_x888, SRC,
|
||||
uint16_t, uint32_t)
|
||||
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_DST (0, neon, 0565_0565, SRC,
|
||||
uint16_t, uint16_t)
|
||||
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_DST (SKIP_ZERO_SRC, neon, 8888_8888, OVER,
|
||||
uint32_t, uint32_t)
|
||||
static force_inline void
|
||||
pixman_scaled_bilinear_scanline_8888_8888_SRC (
|
||||
uint32_t * dst,
|
||||
const uint32_t * mask,
|
||||
const uint32_t * src_top,
|
||||
const uint32_t * src_bottom,
|
||||
int32_t w,
|
||||
int wt,
|
||||
int wb,
|
||||
pixman_fixed_t vx,
|
||||
pixman_fixed_t unit_x,
|
||||
pixman_fixed_t max_vx,
|
||||
pixman_bool_t zero_src)
|
||||
{
|
||||
pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon (dst, src_top, src_bottom, wt, wb, vx, unit_x, w);
|
||||
}
|
||||
|
||||
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_DST (SKIP_ZERO_SRC, neon, 8888_8888, ADD,
|
||||
uint32_t, uint32_t)
|
||||
|
||||
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_A8_DST (0, neon, 8888_8_8888, SRC,
|
||||
uint32_t, uint32_t)
|
||||
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_A8_DST (0, neon, 8888_8_0565, SRC,
|
||||
uint32_t, uint16_t)
|
||||
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_A8_DST (0, neon, 0565_8_x888, SRC,
|
||||
uint16_t, uint32_t)
|
||||
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_A8_DST (0, neon, 0565_8_0565, SRC,
|
||||
uint16_t, uint16_t)
|
||||
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_A8_DST (SKIP_ZERO_SRC, neon, 8888_8_8888, OVER,
|
||||
uint32_t, uint32_t)
|
||||
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_A8_DST (SKIP_ZERO_SRC, neon, 8888_8_8888, ADD,
|
||||
uint32_t, uint32_t)
|
||||
|
||||
void
|
||||
pixman_composite_src_n_8_asm_neon (int32_t w,
|
||||
int32_t h,
|
||||
uint8_t *dst,
|
||||
int32_t dst_stride,
|
||||
uint8_t src);
|
||||
|
||||
void
|
||||
pixman_composite_src_n_0565_asm_neon (int32_t w,
|
||||
int32_t h,
|
||||
uint16_t *dst,
|
||||
int32_t dst_stride,
|
||||
uint16_t src);
|
||||
|
||||
void
|
||||
pixman_composite_src_n_8888_asm_neon (int32_t w,
|
||||
int32_t h,
|
||||
uint32_t *dst,
|
||||
int32_t dst_stride,
|
||||
uint32_t src);
|
||||
|
||||
static pixman_bool_t
|
||||
arm_neon_fill (pixman_implementation_t *imp,
|
||||
uint32_t * bits,
|
||||
int stride,
|
||||
int bpp,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
uint32_t _xor)
|
||||
{
|
||||
/* stride is always multiple of 32bit units in pixman */
|
||||
uint32_t byte_stride = stride * sizeof(uint32_t);
|
||||
|
||||
switch (bpp)
|
||||
{
|
||||
case 8:
|
||||
pixman_composite_src_n_8_asm_neon (
|
||||
width,
|
||||
height,
|
||||
(uint8_t *)(((char *) bits) + y * byte_stride + x),
|
||||
byte_stride,
|
||||
_xor & 0xff);
|
||||
return TRUE;
|
||||
case 16:
|
||||
pixman_composite_src_n_0565_asm_neon (
|
||||
width,
|
||||
height,
|
||||
(uint16_t *)(((char *) bits) + y * byte_stride + x * 2),
|
||||
byte_stride / 2,
|
||||
_xor & 0xffff);
|
||||
return TRUE;
|
||||
case 32:
|
||||
pixman_composite_src_n_8888_asm_neon (
|
||||
width,
|
||||
height,
|
||||
(uint32_t *)(((char *) bits) + y * byte_stride + x * 4),
|
||||
byte_stride / 4,
|
||||
_xor);
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static pixman_bool_t
|
||||
arm_neon_blt (pixman_implementation_t *imp,
|
||||
uint32_t * src_bits,
|
||||
uint32_t * dst_bits,
|
||||
int src_stride,
|
||||
int dst_stride,
|
||||
int src_bpp,
|
||||
int dst_bpp,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dest_x,
|
||||
int dest_y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
if (src_bpp != dst_bpp)
|
||||
return FALSE;
|
||||
|
||||
switch (src_bpp)
|
||||
{
|
||||
case 16:
|
||||
pixman_composite_src_0565_0565_asm_neon (
|
||||
width, height,
|
||||
(uint16_t *)(((char *) dst_bits) +
|
||||
dest_y * dst_stride * 4 + dest_x * 2), dst_stride * 2,
|
||||
(uint16_t *)(((char *) src_bits) +
|
||||
src_y * src_stride * 4 + src_x * 2), src_stride * 2);
|
||||
return TRUE;
|
||||
case 32:
|
||||
pixman_composite_src_8888_8888_asm_neon (
|
||||
width, height,
|
||||
(uint32_t *)(((char *) dst_bits) +
|
||||
dest_y * dst_stride * 4 + dest_x * 4), dst_stride,
|
||||
(uint32_t *)(((char *) src_bits) +
|
||||
src_y * src_stride * 4 + src_x * 4), src_stride);
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void op_bilinear_over_8888_0565(uint16_t *dst, const uint32_t *mask, const uint32_t *src, int width)
|
||||
{
|
||||
pixman_composite_over_8888_0565_asm_neon (width, 1, dst, 0, src, 0);
|
||||
}
|
||||
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (neon_8888_0565_cover_OVER,
|
||||
pixman_scaled_bilinear_scanline_8888_8888_SRC, op_bilinear_over_8888_0565,
|
||||
uint32_t, uint32_t, uint16_t,
|
||||
COVER, FLAG_NONE)
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (neon_8888_0565_pad_OVER,
|
||||
pixman_scaled_bilinear_scanline_8888_8888_SRC, op_bilinear_over_8888_0565,
|
||||
uint32_t, uint32_t, uint16_t,
|
||||
PAD, FLAG_NONE)
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (neon_8888_0565_none_OVER,
|
||||
pixman_scaled_bilinear_scanline_8888_8888_SRC, op_bilinear_over_8888_0565,
|
||||
uint32_t, uint32_t, uint16_t,
|
||||
NONE, FLAG_NONE)
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (neon_8888_0565_normal_OVER,
|
||||
pixman_scaled_bilinear_scanline_8888_8888_SRC, op_bilinear_over_8888_0565,
|
||||
uint32_t, uint32_t, uint16_t,
|
||||
NORMAL, FLAG_NONE)
|
||||
|
||||
static const pixman_fast_path_t arm_neon_fast_paths[] =
|
||||
{
|
||||
PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, r5g6b5, neon_composite_src_0565_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, b5g6r5, neon_composite_src_0565_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, r5g6b5, neon_composite_src_8888_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, r5g6b5, neon_composite_src_8888_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, b5g6r5, neon_composite_src_8888_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, b5g6r5, neon_composite_src_8888_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, a8r8g8b8, neon_composite_src_0565_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, x8r8g8b8, neon_composite_src_0565_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, a8b8g8r8, neon_composite_src_0565_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, x8b8g8r8, neon_composite_src_0565_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, x8r8g8b8, neon_composite_src_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, x8r8g8b8, neon_composite_src_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, x8b8g8r8, neon_composite_src_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, x8b8g8r8, neon_composite_src_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, a8r8g8b8, neon_composite_src_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, a8b8g8r8, neon_composite_src_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, a8r8g8b8, neon_composite_src_x888_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, a8b8g8r8, neon_composite_src_x888_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, r8g8b8, null, r8g8b8, neon_composite_src_0888_0888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, b8g8r8, null, x8r8g8b8, neon_composite_src_0888_8888_rev),
|
||||
PIXMAN_STD_FAST_PATH (SRC, b8g8r8, null, r5g6b5, neon_composite_src_0888_0565_rev),
|
||||
PIXMAN_STD_FAST_PATH (SRC, pixbuf, pixbuf, a8r8g8b8, neon_composite_src_pixbuf_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, pixbuf, pixbuf, a8b8g8r8, neon_composite_src_rpixbuf_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, rpixbuf, rpixbuf, a8r8g8b8, neon_composite_src_rpixbuf_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, rpixbuf, rpixbuf, a8b8g8r8, neon_composite_src_pixbuf_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8r8g8b8, neon_composite_src_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8r8g8b8, neon_composite_src_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8b8g8r8, neon_composite_src_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8b8g8r8, neon_composite_src_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8, neon_composite_src_n_8_8),
|
||||
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8, neon_composite_over_n_8_8),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, a8, r5g6b5, neon_composite_over_n_8_0565),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, a8, b5g6r5, neon_composite_over_n_8_0565),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8r8g8b8, neon_composite_over_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8r8g8b8, neon_composite_over_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8b8g8r8, neon_composite_over_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8b8g8r8, neon_composite_over_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, null, r5g6b5, neon_composite_over_n_0565),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, null, a8r8g8b8, neon_composite_over_n_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, null, x8r8g8b8, neon_composite_over_n_8888),
|
||||
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, a8r8g8b8, neon_composite_over_n_8888_8888_ca),
|
||||
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, x8r8g8b8, neon_composite_over_n_8888_8888_ca),
|
||||
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, a8b8g8r8, neon_composite_over_n_8888_8888_ca),
|
||||
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, x8b8g8r8, neon_composite_over_n_8888_8888_ca),
|
||||
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, r5g6b5, neon_composite_over_n_8888_0565_ca),
|
||||
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, b5g6r5, neon_composite_over_n_8888_0565_ca),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, a8r8g8b8, neon_composite_over_8888_n_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, x8r8g8b8, neon_composite_over_8888_n_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, r5g6b5, neon_composite_over_8888_n_0565),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, solid, b5g6r5, neon_composite_over_8888_n_0565),
|
||||
PIXMAN_STD_FAST_PATH (OVER, r5g6b5, solid, r5g6b5, neon_composite_over_0565_n_0565),
|
||||
PIXMAN_STD_FAST_PATH (OVER, b5g6r5, solid, b5g6r5, neon_composite_over_0565_n_0565),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, a8r8g8b8, neon_composite_over_8888_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, x8r8g8b8, neon_composite_over_8888_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, a8b8g8r8, neon_composite_over_8888_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, x8b8g8r8, neon_composite_over_8888_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, r5g6b5, neon_composite_over_8888_8_0565),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, b5g6r5, neon_composite_over_8888_8_0565),
|
||||
PIXMAN_STD_FAST_PATH (OVER, r5g6b5, a8, r5g6b5, neon_composite_over_0565_8_0565),
|
||||
PIXMAN_STD_FAST_PATH (OVER, b5g6r5, a8, b5g6r5, neon_composite_over_0565_8_0565),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, a8r8g8b8, neon_composite_over_8888_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, r5g6b5, neon_composite_over_8888_0565),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, b5g6r5, neon_composite_over_8888_0565),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, neon_composite_over_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, neon_composite_over_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, neon_composite_over_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, neon_composite_over_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, null, a8r8g8b8, neon_composite_src_x888_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, null, a8b8g8r8, neon_composite_src_x888_8888),
|
||||
PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8, neon_composite_add_n_8_8),
|
||||
PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8r8g8b8, neon_composite_add_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8b8g8r8, neon_composite_add_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (ADD, a8, a8, a8, neon_composite_add_8_8_8),
|
||||
PIXMAN_STD_FAST_PATH (ADD, r5g6b5, a8, r5g6b5, neon_composite_add_0565_8_0565),
|
||||
PIXMAN_STD_FAST_PATH (ADD, b5g6r5, a8, b5g6r5, neon_composite_add_0565_8_0565),
|
||||
PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, a8, a8r8g8b8, neon_composite_add_8888_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, a8, a8b8g8r8, neon_composite_add_8888_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, a8r8g8b8, neon_composite_add_8888_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, solid, a8r8g8b8, neon_composite_add_8888_n_8888),
|
||||
PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, solid, a8b8g8r8, neon_composite_add_8888_n_8888),
|
||||
PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, neon_composite_add_8_8),
|
||||
PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, null, a8r8g8b8, neon_composite_add_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, null, a8b8g8r8, neon_composite_add_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (IN, solid, null, a8, neon_composite_in_n_8),
|
||||
PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8r8g8b8, neon_composite_over_reverse_n_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8b8g8r8, neon_composite_over_reverse_n_8888),
|
||||
PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, r5g6b5, neon_composite_out_reverse_8_0565),
|
||||
PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, b5g6r5, neon_composite_out_reverse_8_0565),
|
||||
PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, a8r8g8b8, neon_composite_out_reverse_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, a8b8g8r8, neon_composite_out_reverse_8_8888),
|
||||
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, neon_8888_8888),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, neon_8888_8888),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, neon_8888_8888),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, neon_8888_8888),
|
||||
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, r5g6b5, neon_8888_0565),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, b5g6r5, neon_8888_0565),
|
||||
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, r5g6b5, neon_8888_0565),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, x8r8g8b8, r5g6b5, neon_8888_0565),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, b5g6r5, neon_8888_0565),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, x8b8g8r8, b5g6r5, neon_8888_0565),
|
||||
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, b5g6r5, x8b8g8r8, neon_0565_8888),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, r5g6b5, x8r8g8b8, neon_0565_8888),
|
||||
/* Note: NONE repeat is not supported yet */
|
||||
SIMPLE_NEAREST_FAST_PATH_COVER (SRC, r5g6b5, a8r8g8b8, neon_0565_8888),
|
||||
SIMPLE_NEAREST_FAST_PATH_COVER (SRC, b5g6r5, a8b8g8r8, neon_0565_8888),
|
||||
SIMPLE_NEAREST_FAST_PATH_PAD (SRC, r5g6b5, a8r8g8b8, neon_0565_8888),
|
||||
SIMPLE_NEAREST_FAST_PATH_PAD (SRC, b5g6r5, a8b8g8r8, neon_0565_8888),
|
||||
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, a8r8g8b8, r5g6b5, neon_8888_8_0565),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, a8b8g8r8, b5g6r5, neon_8888_8_0565),
|
||||
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, r5g6b5, r5g6b5, neon_0565_8_0565),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, b5g6r5, b5g6r5, neon_0565_8_0565),
|
||||
|
||||
SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, neon_8888_8888),
|
||||
SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, neon_8888_8888),
|
||||
SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, neon_8888_8888),
|
||||
|
||||
SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, r5g6b5, neon_8888_0565),
|
||||
SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, r5g6b5, neon_8888_0565),
|
||||
|
||||
SIMPLE_BILINEAR_FAST_PATH (SRC, r5g6b5, x8r8g8b8, neon_0565_x888),
|
||||
SIMPLE_BILINEAR_FAST_PATH (SRC, r5g6b5, r5g6b5, neon_0565_0565),
|
||||
|
||||
SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, neon_8888_8888),
|
||||
SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, neon_8888_8888),
|
||||
|
||||
SIMPLE_BILINEAR_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, neon_8888_8888),
|
||||
SIMPLE_BILINEAR_FAST_PATH (ADD, a8r8g8b8, x8r8g8b8, neon_8888_8888),
|
||||
|
||||
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, neon_8888_8_8888),
|
||||
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, neon_8888_8_8888),
|
||||
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, neon_8888_8_8888),
|
||||
|
||||
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, a8r8g8b8, r5g6b5, neon_8888_8_0565),
|
||||
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, x8r8g8b8, r5g6b5, neon_8888_8_0565),
|
||||
|
||||
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, r5g6b5, x8r8g8b8, neon_0565_8_x888),
|
||||
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, r5g6b5, r5g6b5, neon_0565_8_0565),
|
||||
|
||||
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, neon_8888_8_8888),
|
||||
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, neon_8888_8_8888),
|
||||
|
||||
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, neon_8888_8_8888),
|
||||
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (ADD, a8r8g8b8, x8r8g8b8, neon_8888_8_8888),
|
||||
|
||||
SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, r5g6b5, neon_8888_0565),
|
||||
|
||||
{ PIXMAN_OP_NONE },
|
||||
};
|
||||
|
||||
#define BIND_COMBINE_U(name) \
|
||||
void \
|
||||
pixman_composite_scanline_##name##_mask_asm_neon (int32_t w, \
|
||||
const uint32_t *dst, \
|
||||
const uint32_t *src, \
|
||||
const uint32_t *mask); \
|
||||
\
|
||||
void \
|
||||
pixman_composite_scanline_##name##_asm_neon (int32_t w, \
|
||||
const uint32_t *dst, \
|
||||
const uint32_t *src); \
|
||||
\
|
||||
static void \
|
||||
neon_combine_##name##_u (pixman_implementation_t *imp, \
|
||||
pixman_op_t op, \
|
||||
uint32_t * dest, \
|
||||
const uint32_t * src, \
|
||||
const uint32_t * mask, \
|
||||
int width) \
|
||||
{ \
|
||||
if (mask) \
|
||||
pixman_composite_scanline_##name##_mask_asm_neon (width, dest, \
|
||||
src, mask); \
|
||||
else \
|
||||
pixman_composite_scanline_##name##_asm_neon (width, dest, src); \
|
||||
}
|
||||
|
||||
BIND_COMBINE_U (over)
|
||||
BIND_COMBINE_U (add)
|
||||
BIND_COMBINE_U (out_reverse)
|
||||
|
||||
pixman_implementation_t *
|
||||
_pixman_implementation_create_arm_neon (pixman_implementation_t *fallback)
|
||||
{
|
||||
pixman_implementation_t *imp =
|
||||
_pixman_implementation_create (fallback, arm_neon_fast_paths);
|
||||
|
||||
imp->combine_32[PIXMAN_OP_OVER] = neon_combine_over_u;
|
||||
imp->combine_32[PIXMAN_OP_ADD] = neon_combine_add_u;
|
||||
imp->combine_32[PIXMAN_OP_OUT_REVERSE] = neon_combine_out_reverse_u;
|
||||
|
||||
imp->blt = arm_neon_blt;
|
||||
imp->fill = arm_neon_fill;
|
||||
|
||||
return imp;
|
||||
}
|
||||
165
gfx/cairo/libpixman/src/pixman-arm-simd-asm-scaled.S
Normal file
165
gfx/cairo/libpixman/src/pixman-arm-simd-asm-scaled.S
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* Copyright © 2008 Mozilla Corporation
|
||||
* Copyright © 2010 Nokia Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Mozilla Corporation not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Mozilla Corporation makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Author: Jeff Muizelaar (jeff@infidigm.net)
|
||||
*
|
||||
*/
|
||||
|
||||
/* Prevent the stack from becoming executable */
|
||||
#if defined(__linux__) && defined(__ELF__)
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
#endif
|
||||
|
||||
.text
|
||||
.arch armv6
|
||||
.object_arch armv4
|
||||
.arm
|
||||
.altmacro
|
||||
.p2align 2
|
||||
|
||||
/* Supplementary macro for setting function attributes */
|
||||
.macro pixman_asm_function fname
|
||||
.func fname
|
||||
.global fname
|
||||
#ifdef __ELF__
|
||||
.hidden fname
|
||||
.type fname, %function
|
||||
#endif
|
||||
fname:
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Note: This code is only using armv5te instructions (not even armv6),
|
||||
* but is scheduled for ARM Cortex-A8 pipeline. So it might need to
|
||||
* be split into a few variants, tuned for each microarchitecture.
|
||||
*
|
||||
* TODO: In order to get good performance on ARM9/ARM11 cores (which don't
|
||||
* have efficient write combining), it needs to be changed to use 16-byte
|
||||
* aligned writes using STM instruction.
|
||||
*
|
||||
* Nearest scanline scaler macro template uses the following arguments:
|
||||
* fname - name of the function to generate
|
||||
* bpp_shift - (1 << bpp_shift) is the size of pixel in bytes
|
||||
* t - type suffix for LDR/STR instructions
|
||||
* prefetch_distance - prefetch in the source image by that many
|
||||
* pixels ahead
|
||||
* prefetch_braking_distance - stop prefetching when that many pixels are
|
||||
* remaining before the end of scanline
|
||||
*/
|
||||
|
||||
.macro generate_nearest_scanline_func fname, bpp_shift, t, \
|
||||
prefetch_distance, \
|
||||
prefetch_braking_distance
|
||||
|
||||
pixman_asm_function fname
|
||||
W .req r0
|
||||
DST .req r1
|
||||
SRC .req r2
|
||||
VX .req r3
|
||||
UNIT_X .req ip
|
||||
TMP1 .req r4
|
||||
TMP2 .req r5
|
||||
VXMASK .req r6
|
||||
PF_OFFS .req r7
|
||||
SRC_WIDTH_FIXED .req r8
|
||||
|
||||
ldr UNIT_X, [sp]
|
||||
push {r4, r5, r6, r7, r8, r10}
|
||||
mvn VXMASK, #((1 << bpp_shift) - 1)
|
||||
ldr SRC_WIDTH_FIXED, [sp, #28]
|
||||
|
||||
/* define helper macro */
|
||||
.macro scale_2_pixels
|
||||
ldr&t TMP1, [SRC, TMP1]
|
||||
and TMP2, VXMASK, VX, asr #(16 - bpp_shift)
|
||||
adds VX, VX, UNIT_X
|
||||
str&t TMP1, [DST], #(1 << bpp_shift)
|
||||
9: subpls VX, VX, SRC_WIDTH_FIXED
|
||||
bpl 9b
|
||||
|
||||
ldr&t TMP2, [SRC, TMP2]
|
||||
and TMP1, VXMASK, VX, asr #(16 - bpp_shift)
|
||||
adds VX, VX, UNIT_X
|
||||
str&t TMP2, [DST], #(1 << bpp_shift)
|
||||
9: subpls VX, VX, SRC_WIDTH_FIXED
|
||||
bpl 9b
|
||||
.endm
|
||||
|
||||
/* now do the scaling */
|
||||
and TMP1, VXMASK, VX, asr #(16 - bpp_shift)
|
||||
adds VX, VX, UNIT_X
|
||||
9: subpls VX, VX, SRC_WIDTH_FIXED
|
||||
bpl 9b
|
||||
subs W, W, #(8 + prefetch_braking_distance)
|
||||
blt 2f
|
||||
/* calculate prefetch offset */
|
||||
mov PF_OFFS, #prefetch_distance
|
||||
mla PF_OFFS, UNIT_X, PF_OFFS, VX
|
||||
1: /* main loop, process 8 pixels per iteration with prefetch */
|
||||
pld [SRC, PF_OFFS, asr #(16 - bpp_shift)]
|
||||
add PF_OFFS, UNIT_X, lsl #3
|
||||
scale_2_pixels
|
||||
scale_2_pixels
|
||||
scale_2_pixels
|
||||
scale_2_pixels
|
||||
subs W, W, #8
|
||||
bge 1b
|
||||
2:
|
||||
subs W, W, #(4 - 8 - prefetch_braking_distance)
|
||||
blt 2f
|
||||
1: /* process the remaining pixels */
|
||||
scale_2_pixels
|
||||
scale_2_pixels
|
||||
subs W, W, #4
|
||||
bge 1b
|
||||
2:
|
||||
tst W, #2
|
||||
beq 2f
|
||||
scale_2_pixels
|
||||
2:
|
||||
tst W, #1
|
||||
ldrne&t TMP1, [SRC, TMP1]
|
||||
strne&t TMP1, [DST]
|
||||
/* cleanup helper macro */
|
||||
.purgem scale_2_pixels
|
||||
.unreq DST
|
||||
.unreq SRC
|
||||
.unreq W
|
||||
.unreq VX
|
||||
.unreq UNIT_X
|
||||
.unreq TMP1
|
||||
.unreq TMP2
|
||||
.unreq VXMASK
|
||||
.unreq PF_OFFS
|
||||
.unreq SRC_WIDTH_FIXED
|
||||
/* return */
|
||||
pop {r4, r5, r6, r7, r8, r10}
|
||||
bx lr
|
||||
.endfunc
|
||||
.endm
|
||||
|
||||
generate_nearest_scanline_func \
|
||||
pixman_scaled_nearest_scanline_0565_0565_SRC_asm_armv6, 1, h, 80, 32
|
||||
|
||||
generate_nearest_scanline_func \
|
||||
pixman_scaled_nearest_scanline_8888_8888_SRC_asm_armv6, 2, , 48, 32
|
||||
613
gfx/cairo/libpixman/src/pixman-arm-simd-asm.S
Normal file
613
gfx/cairo/libpixman/src/pixman-arm-simd-asm.S
Normal file
|
|
@ -0,0 +1,613 @@
|
|||
/*
|
||||
* Copyright © 2012 Raspberry Pi Foundation
|
||||
* Copyright © 2012 RISC OS Open Ltd
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of the copyright holders not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. The copyright holders make no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Author: Ben Avison (bavison@riscosopen.org)
|
||||
*
|
||||
*/
|
||||
|
||||
/* Prevent the stack from becoming executable */
|
||||
#if defined(__linux__) && defined(__ELF__)
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
#endif
|
||||
|
||||
.text
|
||||
.arch armv6
|
||||
.object_arch armv4
|
||||
.arm
|
||||
.altmacro
|
||||
.p2align 2
|
||||
|
||||
#include "pixman-arm-simd-asm.h"
|
||||
|
||||
/* A head macro should do all processing which results in an output of up to
|
||||
* 16 bytes, as far as the final load instruction. The corresponding tail macro
|
||||
* should complete the processing of the up-to-16 bytes. The calling macro will
|
||||
* sometimes choose to insert a preload or a decrement of X between them.
|
||||
* cond ARM condition code for code block
|
||||
* numbytes Number of output bytes that should be generated this time
|
||||
* firstreg First WK register in which to place output
|
||||
* unaligned_src Whether to use non-wordaligned loads of source image
|
||||
* unaligned_mask Whether to use non-wordaligned loads of mask image
|
||||
* preload If outputting 16 bytes causes 64 bytes to be read, whether an extra preload should be output
|
||||
*/
|
||||
|
||||
.macro blit_init
|
||||
line_saved_regs STRIDE_D, STRIDE_S
|
||||
.endm
|
||||
|
||||
.macro blit_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload
|
||||
pixld cond, numbytes, firstreg, SRC, unaligned_src
|
||||
.endm
|
||||
|
||||
.macro blit_inner_loop process_head, process_tail, unaligned_src, unaligned_mask, dst_alignment
|
||||
WK4 .req STRIDE_D
|
||||
WK5 .req STRIDE_S
|
||||
WK6 .req MASK
|
||||
WK7 .req STRIDE_M
|
||||
110: pixld , 16, 0, SRC, unaligned_src
|
||||
pixld , 16, 4, SRC, unaligned_src
|
||||
pld [SRC, SCRATCH]
|
||||
pixst , 16, 0, DST
|
||||
pixst , 16, 4, DST
|
||||
subs X, X, #32*8/src_bpp
|
||||
bhs 110b
|
||||
.unreq WK4
|
||||
.unreq WK5
|
||||
.unreq WK6
|
||||
.unreq WK7
|
||||
.endm
|
||||
|
||||
generate_composite_function \
|
||||
pixman_composite_src_8888_8888_asm_armv6, 32, 0, 32, \
|
||||
FLAG_DST_WRITEONLY | FLAG_COND_EXEC | FLAG_SPILL_LINE_VARS_WIDE | FLAG_PROCESS_PRESERVES_SCRATCH, \
|
||||
4, /* prefetch distance */ \
|
||||
blit_init, \
|
||||
nop_macro, /* newline */ \
|
||||
nop_macro, /* cleanup */ \
|
||||
blit_process_head, \
|
||||
nop_macro, /* process tail */ \
|
||||
blit_inner_loop
|
||||
|
||||
generate_composite_function \
|
||||
pixman_composite_src_0565_0565_asm_armv6, 16, 0, 16, \
|
||||
FLAG_DST_WRITEONLY | FLAG_COND_EXEC | FLAG_SPILL_LINE_VARS_WIDE | FLAG_PROCESS_PRESERVES_SCRATCH, \
|
||||
4, /* prefetch distance */ \
|
||||
blit_init, \
|
||||
nop_macro, /* newline */ \
|
||||
nop_macro, /* cleanup */ \
|
||||
blit_process_head, \
|
||||
nop_macro, /* process tail */ \
|
||||
blit_inner_loop
|
||||
|
||||
generate_composite_function \
|
||||
pixman_composite_src_8_8_asm_armv6, 8, 0, 8, \
|
||||
FLAG_DST_WRITEONLY | FLAG_COND_EXEC | FLAG_SPILL_LINE_VARS_WIDE | FLAG_PROCESS_PRESERVES_SCRATCH, \
|
||||
3, /* prefetch distance */ \
|
||||
blit_init, \
|
||||
nop_macro, /* newline */ \
|
||||
nop_macro, /* cleanup */ \
|
||||
blit_process_head, \
|
||||
nop_macro, /* process tail */ \
|
||||
blit_inner_loop
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.macro src_n_8888_init
|
||||
ldr SRC, [sp, #ARGS_STACK_OFFSET]
|
||||
mov STRIDE_S, SRC
|
||||
mov MASK, SRC
|
||||
mov STRIDE_M, SRC
|
||||
.endm
|
||||
|
||||
.macro src_n_0565_init
|
||||
ldrh SRC, [sp, #ARGS_STACK_OFFSET]
|
||||
orr SRC, SRC, lsl #16
|
||||
mov STRIDE_S, SRC
|
||||
mov MASK, SRC
|
||||
mov STRIDE_M, SRC
|
||||
.endm
|
||||
|
||||
.macro src_n_8_init
|
||||
ldrb SRC, [sp, #ARGS_STACK_OFFSET]
|
||||
orr SRC, SRC, lsl #8
|
||||
orr SRC, SRC, lsl #16
|
||||
mov STRIDE_S, SRC
|
||||
mov MASK, SRC
|
||||
mov STRIDE_M, SRC
|
||||
.endm
|
||||
|
||||
.macro fill_process_tail cond, numbytes, firstreg
|
||||
WK4 .req SRC
|
||||
WK5 .req STRIDE_S
|
||||
WK6 .req MASK
|
||||
WK7 .req STRIDE_M
|
||||
pixst cond, numbytes, 4, DST
|
||||
.unreq WK4
|
||||
.unreq WK5
|
||||
.unreq WK6
|
||||
.unreq WK7
|
||||
.endm
|
||||
|
||||
generate_composite_function \
|
||||
pixman_composite_src_n_8888_asm_armv6, 0, 0, 32, \
|
||||
FLAG_DST_WRITEONLY | FLAG_COND_EXEC | FLAG_PROCESS_PRESERVES_PSR | FLAG_PROCESS_DOES_STORE | FLAG_PROCESS_PRESERVES_SCRATCH \
|
||||
0, /* prefetch distance doesn't apply */ \
|
||||
src_n_8888_init \
|
||||
nop_macro, /* newline */ \
|
||||
nop_macro /* cleanup */ \
|
||||
nop_macro /* process head */ \
|
||||
fill_process_tail
|
||||
|
||||
generate_composite_function \
|
||||
pixman_composite_src_n_0565_asm_armv6, 0, 0, 16, \
|
||||
FLAG_DST_WRITEONLY | FLAG_COND_EXEC | FLAG_PROCESS_PRESERVES_PSR | FLAG_PROCESS_DOES_STORE | FLAG_PROCESS_PRESERVES_SCRATCH \
|
||||
0, /* prefetch distance doesn't apply */ \
|
||||
src_n_0565_init \
|
||||
nop_macro, /* newline */ \
|
||||
nop_macro /* cleanup */ \
|
||||
nop_macro /* process head */ \
|
||||
fill_process_tail
|
||||
|
||||
generate_composite_function \
|
||||
pixman_composite_src_n_8_asm_armv6, 0, 0, 8, \
|
||||
FLAG_DST_WRITEONLY | FLAG_COND_EXEC | FLAG_PROCESS_PRESERVES_PSR | FLAG_PROCESS_DOES_STORE | FLAG_PROCESS_PRESERVES_SCRATCH \
|
||||
0, /* prefetch distance doesn't apply */ \
|
||||
src_n_8_init \
|
||||
nop_macro, /* newline */ \
|
||||
nop_macro /* cleanup */ \
|
||||
nop_macro /* process head */ \
|
||||
fill_process_tail
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.macro src_x888_8888_pixel, cond, reg
|
||||
orr&cond WK®, WK®, #0xFF000000
|
||||
.endm
|
||||
|
||||
.macro pixman_composite_src_x888_8888_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload
|
||||
pixld cond, numbytes, firstreg, SRC, unaligned_src
|
||||
.endm
|
||||
|
||||
.macro pixman_composite_src_x888_8888_process_tail cond, numbytes, firstreg
|
||||
src_x888_8888_pixel cond, %(firstreg+0)
|
||||
.if numbytes >= 8
|
||||
src_x888_8888_pixel cond, %(firstreg+1)
|
||||
.if numbytes == 16
|
||||
src_x888_8888_pixel cond, %(firstreg+2)
|
||||
src_x888_8888_pixel cond, %(firstreg+3)
|
||||
.endif
|
||||
.endif
|
||||
.endm
|
||||
|
||||
generate_composite_function \
|
||||
pixman_composite_src_x888_8888_asm_armv6, 32, 0, 32, \
|
||||
FLAG_DST_WRITEONLY | FLAG_COND_EXEC | FLAG_PROCESS_PRESERVES_SCRATCH, \
|
||||
3, /* prefetch distance */ \
|
||||
nop_macro, /* init */ \
|
||||
nop_macro, /* newline */ \
|
||||
nop_macro, /* cleanup */ \
|
||||
pixman_composite_src_x888_8888_process_head, \
|
||||
pixman_composite_src_x888_8888_process_tail
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.macro src_0565_8888_init
|
||||
/* Hold loop invariants in MASK and STRIDE_M */
|
||||
ldr MASK, =0x07E007E0
|
||||
mov STRIDE_M, #0xFF000000
|
||||
/* Set GE[3:0] to 1010 so SEL instructions do what we want */
|
||||
ldr SCRATCH, =0x80008000
|
||||
uadd8 SCRATCH, SCRATCH, SCRATCH
|
||||
.endm
|
||||
|
||||
.macro src_0565_8888_2pixels, reg1, reg2
|
||||
and SCRATCH, WK®1, MASK @ 00000GGGGGG0000000000gggggg00000
|
||||
bic WK®2, WK®1, MASK @ RRRRR000000BBBBBrrrrr000000bbbbb
|
||||
orr SCRATCH, SCRATCH, SCRATCH, lsr #6 @ 00000GGGGGGGGGGGG0000ggggggggggg
|
||||
mov WK®1, WK®2, lsl #16 @ rrrrr000000bbbbb0000000000000000
|
||||
mov SCRATCH, SCRATCH, ror #19 @ GGGG0000ggggggggggg00000GGGGGGGG
|
||||
bic WK®2, WK®2, WK®1, lsr #16 @ RRRRR000000BBBBB0000000000000000
|
||||
orr WK®1, WK®1, WK®1, lsr #5 @ rrrrrrrrrr0bbbbbbbbbb00000000000
|
||||
orr WK®2, WK®2, WK®2, lsr #5 @ RRRRRRRRRR0BBBBBBBBBB00000000000
|
||||
pkhtb WK®1, WK®1, WK®1, asr #5 @ rrrrrrrr--------bbbbbbbb--------
|
||||
sel WK®1, WK®1, SCRATCH @ rrrrrrrrggggggggbbbbbbbb--------
|
||||
mov SCRATCH, SCRATCH, ror #16 @ ggg00000GGGGGGGGGGGG0000gggggggg
|
||||
pkhtb WK®2, WK®2, WK®2, asr #5 @ RRRRRRRR--------BBBBBBBB--------
|
||||
sel WK®2, WK®2, SCRATCH @ RRRRRRRRGGGGGGGGBBBBBBBB--------
|
||||
orr WK®1, STRIDE_M, WK®1, lsr #8 @ 11111111rrrrrrrrggggggggbbbbbbbb
|
||||
orr WK®2, STRIDE_M, WK®2, lsr #8 @ 11111111RRRRRRRRGGGGGGGGBBBBBBBB
|
||||
.endm
|
||||
|
||||
/* This version doesn't need STRIDE_M, but is one instruction longer.
|
||||
It would however be preferable for an XRGB target, since we could knock off the last 2 instructions, but is that a common case?
|
||||
and SCRATCH, WK®1, MASK @ 00000GGGGGG0000000000gggggg00000
|
||||
bic WK®1, WK®1, MASK @ RRRRR000000BBBBBrrrrr000000bbbbb
|
||||
orr SCRATCH, SCRATCH, SCRATCH, lsr #6 @ 00000GGGGGGGGGGGG0000ggggggggggg
|
||||
mov WK®2, WK®1, lsr #16 @ 0000000000000000RRRRR000000BBBBB
|
||||
mov SCRATCH, SCRATCH, ror #27 @ GGGGGGGGGGGG0000ggggggggggg00000
|
||||
bic WK®1, WK®1, WK®2, lsl #16 @ 0000000000000000rrrrr000000bbbbb
|
||||
mov WK®2, WK®2, lsl #3 @ 0000000000000RRRRR000000BBBBB000
|
||||
mov WK®1, WK®1, lsl #3 @ 0000000000000rrrrr000000bbbbb000
|
||||
orr WK®2, WK®2, WK®2, lsr #5 @ 0000000000000RRRRRRRRRR0BBBBBBBB
|
||||
orr WK®1, WK®1, WK®1, lsr #5 @ 0000000000000rrrrrrrrrr0bbbbbbbb
|
||||
pkhbt WK®2, WK®2, WK®2, lsl #5 @ --------RRRRRRRR--------BBBBBBBB
|
||||
pkhbt WK®1, WK®1, WK®1, lsl #5 @ --------rrrrrrrr--------bbbbbbbb
|
||||
sel WK®2, SCRATCH, WK®2 @ --------RRRRRRRRGGGGGGGGBBBBBBBB
|
||||
sel WK®1, SCRATCH, WK®1 @ --------rrrrrrrrggggggggbbbbbbbb
|
||||
orr WK®2, WK®2, #0xFF000000 @ 11111111RRRRRRRRGGGGGGGGBBBBBBBB
|
||||
orr WK®1, WK®1, #0xFF000000 @ 11111111rrrrrrrrggggggggbbbbbbbb
|
||||
*/
|
||||
|
||||
.macro src_0565_8888_1pixel, reg
|
||||
bic SCRATCH, WK®, MASK @ 0000000000000000rrrrr000000bbbbb
|
||||
and WK®, WK®, MASK @ 000000000000000000000gggggg00000
|
||||
mov SCRATCH, SCRATCH, lsl #3 @ 0000000000000rrrrr000000bbbbb000
|
||||
mov WK®, WK®, lsl #5 @ 0000000000000000gggggg0000000000
|
||||
orr SCRATCH, SCRATCH, SCRATCH, lsr #5 @ 0000000000000rrrrrrrrrr0bbbbbbbb
|
||||
orr WK®, WK®, WK®, lsr #6 @ 000000000000000gggggggggggg00000
|
||||
pkhbt SCRATCH, SCRATCH, SCRATCH, lsl #5 @ --------rrrrrrrr--------bbbbbbbb
|
||||
sel WK®, WK®, SCRATCH @ --------rrrrrrrrggggggggbbbbbbbb
|
||||
orr WK®, WK®, #0xFF000000 @ 11111111rrrrrrrrggggggggbbbbbbbb
|
||||
.endm
|
||||
|
||||
.macro src_0565_8888_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload
|
||||
.if numbytes == 16
|
||||
pixldst ld,, 8, firstreg, %(firstreg+2),,, SRC, unaligned_src
|
||||
.elseif numbytes == 8
|
||||
pixld , 4, firstreg, SRC, unaligned_src
|
||||
.elseif numbytes == 4
|
||||
pixld , 2, firstreg, SRC, unaligned_src
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro src_0565_8888_process_tail cond, numbytes, firstreg
|
||||
.if numbytes == 16
|
||||
src_0565_8888_2pixels firstreg, %(firstreg+1)
|
||||
src_0565_8888_2pixels %(firstreg+2), %(firstreg+3)
|
||||
.elseif numbytes == 8
|
||||
src_0565_8888_2pixels firstreg, %(firstreg+1)
|
||||
.else
|
||||
src_0565_8888_1pixel firstreg
|
||||
.endif
|
||||
.endm
|
||||
|
||||
generate_composite_function \
|
||||
pixman_composite_src_0565_8888_asm_armv6, 16, 0, 32, \
|
||||
FLAG_DST_WRITEONLY | FLAG_BRANCH_OVER, \
|
||||
3, /* prefetch distance */ \
|
||||
src_0565_8888_init, \
|
||||
nop_macro, /* newline */ \
|
||||
nop_macro, /* cleanup */ \
|
||||
src_0565_8888_process_head, \
|
||||
src_0565_8888_process_tail
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.macro add_8_8_8pixels cond, dst1, dst2
|
||||
uqadd8&cond WK&dst1, WK&dst1, MASK
|
||||
uqadd8&cond WK&dst2, WK&dst2, STRIDE_M
|
||||
.endm
|
||||
|
||||
.macro add_8_8_4pixels cond, dst
|
||||
uqadd8&cond WK&dst, WK&dst, MASK
|
||||
.endm
|
||||
|
||||
.macro add_8_8_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload
|
||||
WK4 .req MASK
|
||||
WK5 .req STRIDE_M
|
||||
.if numbytes == 16
|
||||
pixld cond, 8, 4, SRC, unaligned_src
|
||||
pixld cond, 16, firstreg, DST, 0
|
||||
add_8_8_8pixels cond, firstreg, %(firstreg+1)
|
||||
pixld cond, 8, 4, SRC, unaligned_src
|
||||
.else
|
||||
pixld cond, numbytes, 4, SRC, unaligned_src
|
||||
pixld cond, numbytes, firstreg, DST, 0
|
||||
.endif
|
||||
.unreq WK4
|
||||
.unreq WK5
|
||||
.endm
|
||||
|
||||
.macro add_8_8_process_tail cond, numbytes, firstreg
|
||||
.if numbytes == 16
|
||||
add_8_8_8pixels cond, %(firstreg+2), %(firstreg+3)
|
||||
.elseif numbytes == 8
|
||||
add_8_8_8pixels cond, firstreg, %(firstreg+1)
|
||||
.else
|
||||
add_8_8_4pixels cond, firstreg
|
||||
.endif
|
||||
.endm
|
||||
|
||||
generate_composite_function \
|
||||
pixman_composite_add_8_8_asm_armv6, 8, 0, 8, \
|
||||
FLAG_DST_READWRITE | FLAG_BRANCH_OVER | FLAG_PROCESS_PRESERVES_SCRATCH, \
|
||||
2, /* prefetch distance */ \
|
||||
nop_macro, /* init */ \
|
||||
nop_macro, /* newline */ \
|
||||
nop_macro, /* cleanup */ \
|
||||
add_8_8_process_head, \
|
||||
add_8_8_process_tail
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.macro over_8888_8888_init
|
||||
/* Hold loop invariant in MASK */
|
||||
ldr MASK, =0x00800080
|
||||
/* Set GE[3:0] to 0101 so SEL instructions do what we want */
|
||||
uadd8 SCRATCH, MASK, MASK
|
||||
line_saved_regs STRIDE_D, STRIDE_S, ORIG_W
|
||||
.endm
|
||||
|
||||
.macro over_8888_8888_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload
|
||||
WK4 .req STRIDE_D
|
||||
WK5 .req STRIDE_S
|
||||
WK6 .req STRIDE_M
|
||||
WK7 .req ORIG_W
|
||||
pixld , numbytes, %(4+firstreg), SRC, unaligned_src
|
||||
pixld , numbytes, firstreg, DST, 0
|
||||
.unreq WK4
|
||||
.unreq WK5
|
||||
.unreq WK6
|
||||
.unreq WK7
|
||||
.endm
|
||||
|
||||
.macro over_8888_8888_check_transparent numbytes, reg0, reg1, reg2, reg3
|
||||
/* Since these colours a premultiplied by alpha, only 0 indicates transparent (any other colour with 0 in the alpha byte is luminous) */
|
||||
teq WK®0, #0
|
||||
.if numbytes > 4
|
||||
teqeq WK®1, #0
|
||||
.if numbytes > 8
|
||||
teqeq WK®2, #0
|
||||
teqeq WK®3, #0
|
||||
.endif
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro over_8888_8888_prepare next
|
||||
mov WK&next, WK&next, lsr #24
|
||||
.endm
|
||||
|
||||
.macro over_8888_8888_1pixel src, dst, offset, next
|
||||
/* src = destination component multiplier */
|
||||
rsb WK&src, WK&src, #255
|
||||
/* Split even/odd bytes of dst into SCRATCH/dst */
|
||||
uxtb16 SCRATCH, WK&dst
|
||||
uxtb16 WK&dst, WK&dst, ror #8
|
||||
/* Multiply through, adding 0.5 to the upper byte of result for rounding */
|
||||
mla SCRATCH, SCRATCH, WK&src, MASK
|
||||
mla WK&dst, WK&dst, WK&src, MASK
|
||||
/* Where we would have had a stall between the result of the first MLA and the shifter input,
|
||||
* reload the complete source pixel */
|
||||
ldr WK&src, [SRC, #offset]
|
||||
/* Multiply by 257/256 to approximate 256/255 */
|
||||
uxtab16 SCRATCH, SCRATCH, SCRATCH, ror #8
|
||||
/* In this stall, start processing the next pixel */
|
||||
.if offset < -4
|
||||
mov WK&next, WK&next, lsr #24
|
||||
.endif
|
||||
uxtab16 WK&dst, WK&dst, WK&dst, ror #8
|
||||
/* Recombine even/odd bytes of multiplied destination */
|
||||
mov SCRATCH, SCRATCH, ror #8
|
||||
sel WK&dst, SCRATCH, WK&dst
|
||||
/* Saturated add of source to multiplied destination */
|
||||
uqadd8 WK&dst, WK&dst, WK&src
|
||||
.endm
|
||||
|
||||
.macro over_8888_8888_process_tail cond, numbytes, firstreg
|
||||
WK4 .req STRIDE_D
|
||||
WK5 .req STRIDE_S
|
||||
WK6 .req STRIDE_M
|
||||
WK7 .req ORIG_W
|
||||
over_8888_8888_check_transparent numbytes, %(4+firstreg), %(5+firstreg), %(6+firstreg), %(7+firstreg)
|
||||
beq 10f
|
||||
over_8888_8888_prepare %(4+firstreg)
|
||||
.set PROCESS_REG, firstreg
|
||||
.set PROCESS_OFF, -numbytes
|
||||
.rept numbytes / 4
|
||||
over_8888_8888_1pixel %(4+PROCESS_REG), %(0+PROCESS_REG), PROCESS_OFF, %(5+PROCESS_REG)
|
||||
.set PROCESS_REG, PROCESS_REG+1
|
||||
.set PROCESS_OFF, PROCESS_OFF+4
|
||||
.endr
|
||||
pixst , numbytes, firstreg, DST
|
||||
10:
|
||||
.unreq WK4
|
||||
.unreq WK5
|
||||
.unreq WK6
|
||||
.unreq WK7
|
||||
.endm
|
||||
|
||||
generate_composite_function \
|
||||
pixman_composite_over_8888_8888_asm_armv6, 32, 0, 32 \
|
||||
FLAG_DST_READWRITE | FLAG_BRANCH_OVER | FLAG_PROCESS_CORRUPTS_PSR | FLAG_PROCESS_DOES_STORE | FLAG_SPILL_LINE_VARS \
|
||||
2, /* prefetch distance */ \
|
||||
over_8888_8888_init, \
|
||||
nop_macro, /* newline */ \
|
||||
nop_macro, /* cleanup */ \
|
||||
over_8888_8888_process_head, \
|
||||
over_8888_8888_process_tail
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/* Multiply each byte of a word by a byte.
|
||||
* Useful when there aren't any obvious ways to fill the stalls with other instructions.
|
||||
* word Register containing 4 bytes
|
||||
* byte Register containing byte multiplier (bits 8-31 must be 0)
|
||||
* tmp Scratch register
|
||||
* half Register containing the constant 0x00800080
|
||||
* GE[3:0] bits must contain 0101
|
||||
*/
|
||||
.macro mul_8888_8 word, byte, tmp, half
|
||||
/* Split even/odd bytes of word apart */
|
||||
uxtb16 tmp, word
|
||||
uxtb16 word, word, ror #8
|
||||
/* Multiply bytes together with rounding, then by 257/256 */
|
||||
mla tmp, tmp, byte, half
|
||||
mla word, word, byte, half /* 1 stall follows */
|
||||
uxtab16 tmp, tmp, tmp, ror #8 /* 1 stall follows */
|
||||
uxtab16 word, word, word, ror #8
|
||||
/* Recombine bytes */
|
||||
mov tmp, tmp, ror #8
|
||||
sel word, tmp, word
|
||||
.endm
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.macro over_8888_n_8888_init
|
||||
/* Mask is constant */
|
||||
ldr MASK, [sp, #ARGS_STACK_OFFSET+8]
|
||||
/* Hold loop invariant in STRIDE_M */
|
||||
ldr STRIDE_M, =0x00800080
|
||||
/* We only want the alpha bits of the constant mask */
|
||||
mov MASK, MASK, lsr #24
|
||||
/* Set GE[3:0] to 0101 so SEL instructions do what we want */
|
||||
uadd8 SCRATCH, STRIDE_M, STRIDE_M
|
||||
line_saved_regs Y, STRIDE_D, STRIDE_S, ORIG_W
|
||||
.endm
|
||||
|
||||
.macro over_8888_n_8888_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload
|
||||
WK4 .req Y
|
||||
WK5 .req STRIDE_D
|
||||
WK6 .req STRIDE_S
|
||||
WK7 .req ORIG_W
|
||||
pixld , numbytes, %(4+(firstreg%2)), SRC, unaligned_src
|
||||
pixld , numbytes, firstreg, DST, 0
|
||||
.unreq WK4
|
||||
.unreq WK5
|
||||
.unreq WK6
|
||||
.unreq WK7
|
||||
.endm
|
||||
|
||||
.macro over_8888_n_8888_1pixel src, dst
|
||||
mul_8888_8 WK&src, MASK, SCRATCH, STRIDE_M
|
||||
sub WK7, WK6, WK&src, lsr #24
|
||||
mul_8888_8 WK&dst, WK7, SCRATCH, STRIDE_M
|
||||
uqadd8 WK&dst, WK&dst, WK&src
|
||||
.endm
|
||||
|
||||
.macro over_8888_n_8888_process_tail cond, numbytes, firstreg
|
||||
WK4 .req Y
|
||||
WK5 .req STRIDE_D
|
||||
WK6 .req STRIDE_S
|
||||
WK7 .req ORIG_W
|
||||
over_8888_8888_check_transparent numbytes, %(4+(firstreg%2)), %(5+(firstreg%2)), %(6+firstreg), %(7+firstreg)
|
||||
beq 10f
|
||||
mov WK6, #255
|
||||
.set PROCESS_REG, firstreg
|
||||
.rept numbytes / 4
|
||||
.if numbytes == 16 && PROCESS_REG == 2
|
||||
/* We're using WK6 and WK7 as temporaries, so half way through
|
||||
* 4 pixels, reload the second two source pixels but this time
|
||||
* into WK4 and WK5 */
|
||||
ldmdb SRC, {WK4, WK5}
|
||||
.endif
|
||||
over_8888_n_8888_1pixel %(4+(PROCESS_REG%2)), %(PROCESS_REG)
|
||||
.set PROCESS_REG, PROCESS_REG+1
|
||||
.endr
|
||||
pixst , numbytes, firstreg, DST
|
||||
10:
|
||||
.unreq WK4
|
||||
.unreq WK5
|
||||
.unreq WK6
|
||||
.unreq WK7
|
||||
.endm
|
||||
|
||||
generate_composite_function \
|
||||
pixman_composite_over_8888_n_8888_asm_armv6, 32, 0, 32 \
|
||||
FLAG_DST_READWRITE | FLAG_BRANCH_OVER | FLAG_PROCESS_CORRUPTS_PSR | FLAG_PROCESS_DOES_STORE | FLAG_SPILL_LINE_VARS \
|
||||
2, /* prefetch distance */ \
|
||||
over_8888_n_8888_init, \
|
||||
nop_macro, /* newline */ \
|
||||
nop_macro, /* cleanup */ \
|
||||
over_8888_n_8888_process_head, \
|
||||
over_8888_n_8888_process_tail
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.macro over_n_8_8888_init
|
||||
/* Source is constant, but splitting it into even/odd bytes is a loop invariant */
|
||||
ldr SRC, [sp, #ARGS_STACK_OFFSET]
|
||||
/* Not enough registers to hold this constant, but we still use it here to set GE[3:0] */
|
||||
ldr SCRATCH, =0x00800080
|
||||
uxtb16 STRIDE_S, SRC
|
||||
uxtb16 SRC, SRC, ror #8
|
||||
/* Set GE[3:0] to 0101 so SEL instructions do what we want */
|
||||
uadd8 SCRATCH, SCRATCH, SCRATCH
|
||||
line_saved_regs Y, STRIDE_D, STRIDE_M, ORIG_W
|
||||
.endm
|
||||
|
||||
.macro over_n_8_8888_newline
|
||||
ldr STRIDE_D, =0x00800080
|
||||
b 1f
|
||||
.ltorg
|
||||
1:
|
||||
.endm
|
||||
|
||||
.macro over_n_8_8888_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload
|
||||
WK4 .req STRIDE_M
|
||||
pixld , numbytes/4, 4, MASK, unaligned_mask
|
||||
pixld , numbytes, firstreg, DST, 0
|
||||
.unreq WK4
|
||||
.endm
|
||||
|
||||
.macro over_n_8_8888_1pixel src, dst
|
||||
uxtb Y, WK4, ror #src*8
|
||||
/* Trailing part of multiplication of source */
|
||||
mla SCRATCH, STRIDE_S, Y, STRIDE_D
|
||||
mla Y, SRC, Y, STRIDE_D
|
||||
mov ORIG_W, #255
|
||||
uxtab16 SCRATCH, SCRATCH, SCRATCH, ror #8
|
||||
uxtab16 Y, Y, Y, ror #8
|
||||
mov SCRATCH, SCRATCH, ror #8
|
||||
sub ORIG_W, ORIG_W, Y, lsr #24
|
||||
sel Y, SCRATCH, Y
|
||||
/* Then multiply the destination */
|
||||
mul_8888_8 WK&dst, ORIG_W, SCRATCH, STRIDE_D
|
||||
uqadd8 WK&dst, WK&dst, Y
|
||||
.endm
|
||||
|
||||
.macro over_n_8_8888_process_tail cond, numbytes, firstreg
|
||||
WK4 .req STRIDE_M
|
||||
teq WK4, #0
|
||||
beq 10f
|
||||
.set PROCESS_REG, firstreg
|
||||
.rept numbytes / 4
|
||||
over_n_8_8888_1pixel %(PROCESS_REG-firstreg), %(PROCESS_REG)
|
||||
.set PROCESS_REG, PROCESS_REG+1
|
||||
.endr
|
||||
pixst , numbytes, firstreg, DST
|
||||
10:
|
||||
.unreq WK4
|
||||
.endm
|
||||
|
||||
generate_composite_function \
|
||||
pixman_composite_over_n_8_8888_asm_armv6, 0, 8, 32 \
|
||||
FLAG_DST_READWRITE | FLAG_BRANCH_OVER | FLAG_PROCESS_CORRUPTS_PSR | FLAG_PROCESS_DOES_STORE | FLAG_SPILL_LINE_VARS \
|
||||
2, /* prefetch distance */ \
|
||||
over_n_8_8888_init, \
|
||||
over_n_8_8888_newline, \
|
||||
nop_macro, /* cleanup */ \
|
||||
over_n_8_8888_process_head, \
|
||||
over_n_8_8888_process_tail
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
912
gfx/cairo/libpixman/src/pixman-arm-simd-asm.h
Normal file
912
gfx/cairo/libpixman/src/pixman-arm-simd-asm.h
Normal file
|
|
@ -0,0 +1,912 @@
|
|||
/*
|
||||
* Copyright © 2012 Raspberry Pi Foundation
|
||||
* Copyright © 2012 RISC OS Open Ltd
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of the copyright holders not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. The copyright holders make no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Author: Ben Avison (bavison@riscosopen.org)
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Because the alignment of pixel data to cachelines, and even the number of
|
||||
* cachelines per row can vary from row to row, and because of the need to
|
||||
* preload each scanline once and only once, this prefetch strategy treats
|
||||
* each row of pixels independently. When a pixel row is long enough, there
|
||||
* are three distinct phases of prefetch:
|
||||
* * an inner loop section, where each time a cacheline of data is
|
||||
* processed, another cacheline is preloaded (the exact distance ahead is
|
||||
* determined empirically using profiling results from lowlevel-blt-bench)
|
||||
* * a leading section, where enough cachelines are preloaded to ensure no
|
||||
* cachelines escape being preloaded when the inner loop starts
|
||||
* * a trailing section, where a limited number (0 or more) of cachelines
|
||||
* are preloaded to deal with data (if any) that hangs off the end of the
|
||||
* last iteration of the inner loop, plus any trailing bytes that were not
|
||||
* enough to make up one whole iteration of the inner loop
|
||||
*
|
||||
* There are (in general) three distinct code paths, selected between
|
||||
* depending upon how long the pixel row is. If it is long enough that there
|
||||
* is at least one iteration of the inner loop (as described above) then
|
||||
* this is described as the "wide" case. If it is shorter than that, but
|
||||
* there are still enough bytes output that there is at least one 16-byte-
|
||||
* long, 16-byte-aligned write to the destination (the optimum type of
|
||||
* write), then this is the "medium" case. If it is not even this long, then
|
||||
* this is the "narrow" case, and there is no attempt to align writes to
|
||||
* 16-byte boundaries. In the "medium" and "narrow" cases, all the
|
||||
* cachelines containing data from the pixel row are prefetched up-front.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Determine whether we put the arguments on the stack for debugging.
|
||||
*/
|
||||
#undef DEBUG_PARAMS
|
||||
|
||||
/*
|
||||
* Bit flags for 'generate_composite_function' macro which are used
|
||||
* to tune generated functions behavior.
|
||||
*/
|
||||
.set FLAG_DST_WRITEONLY, 0
|
||||
.set FLAG_DST_READWRITE, 1
|
||||
.set FLAG_COND_EXEC, 0
|
||||
.set FLAG_BRANCH_OVER, 2
|
||||
.set FLAG_PROCESS_PRESERVES_PSR, 0
|
||||
.set FLAG_PROCESS_CORRUPTS_PSR, 4
|
||||
.set FLAG_PROCESS_DOESNT_STORE, 0
|
||||
.set FLAG_PROCESS_DOES_STORE, 8 /* usually because it needs to conditionally skip it */
|
||||
.set FLAG_NO_SPILL_LINE_VARS, 0
|
||||
.set FLAG_SPILL_LINE_VARS_WIDE, 16
|
||||
.set FLAG_SPILL_LINE_VARS_NON_WIDE, 32
|
||||
.set FLAG_SPILL_LINE_VARS, 48
|
||||
.set FLAG_PROCESS_CORRUPTS_SCRATCH, 0
|
||||
.set FLAG_PROCESS_PRESERVES_SCRATCH, 64
|
||||
|
||||
/*
|
||||
* Offset into stack where mask and source pointer/stride can be accessed.
|
||||
*/
|
||||
#ifdef DEBUG_PARAMS
|
||||
.set ARGS_STACK_OFFSET, (9*4+9*4)
|
||||
#else
|
||||
.set ARGS_STACK_OFFSET, (9*4)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Constants for selecting preferable prefetch type.
|
||||
*/
|
||||
.set PREFETCH_TYPE_NONE, 0
|
||||
.set PREFETCH_TYPE_STANDARD, 1
|
||||
|
||||
/*
|
||||
* Definitions of macros for load/store of pixel data.
|
||||
*/
|
||||
|
||||
.macro pixldst op, cond=al, numbytes, reg0, reg1, reg2, reg3, base, unaligned=0
|
||||
.if numbytes == 16
|
||||
.if unaligned == 1
|
||||
op&r&cond WK®0, [base], #4
|
||||
op&r&cond WK®1, [base], #4
|
||||
op&r&cond WK®2, [base], #4
|
||||
op&r&cond WK®3, [base], #4
|
||||
.else
|
||||
op&m&cond&ia base!, {WK®0,WK®1,WK®2,WK®3}
|
||||
.endif
|
||||
.elseif numbytes == 8
|
||||
.if unaligned == 1
|
||||
op&r&cond WK®0, [base], #4
|
||||
op&r&cond WK®1, [base], #4
|
||||
.else
|
||||
op&m&cond&ia base!, {WK®0,WK®1}
|
||||
.endif
|
||||
.elseif numbytes == 4
|
||||
op&r&cond WK®0, [base], #4
|
||||
.elseif numbytes == 2
|
||||
op&r&cond&h WK®0, [base], #2
|
||||
.elseif numbytes == 1
|
||||
op&r&cond&b WK®0, [base], #1
|
||||
.else
|
||||
.error "unsupported size: numbytes"
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro pixst_baseupdated cond, numbytes, reg0, reg1, reg2, reg3, base
|
||||
.if numbytes == 16
|
||||
stm&cond&db base, {WK®0,WK®1,WK®2,WK®3}
|
||||
.elseif numbytes == 8
|
||||
stm&cond&db base, {WK®0,WK®1}
|
||||
.elseif numbytes == 4
|
||||
str&cond WK®0, [base, #-4]
|
||||
.elseif numbytes == 2
|
||||
str&cond&h WK®0, [base, #-2]
|
||||
.elseif numbytes == 1
|
||||
str&cond&b WK®0, [base, #-1]
|
||||
.else
|
||||
.error "unsupported size: numbytes"
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro pixld cond, numbytes, firstreg, base, unaligned
|
||||
pixldst ld, cond, numbytes, %(firstreg+0), %(firstreg+1), %(firstreg+2), %(firstreg+3), base, unaligned
|
||||
.endm
|
||||
|
||||
.macro pixst cond, numbytes, firstreg, base
|
||||
.if (flags) & FLAG_DST_READWRITE
|
||||
pixst_baseupdated cond, numbytes, %(firstreg+0), %(firstreg+1), %(firstreg+2), %(firstreg+3), base
|
||||
.else
|
||||
pixldst st, cond, numbytes, %(firstreg+0), %(firstreg+1), %(firstreg+2), %(firstreg+3), base
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro PF a, x:vararg
|
||||
.if (PREFETCH_TYPE_CURRENT == PREFETCH_TYPE_STANDARD)
|
||||
a x
|
||||
.endif
|
||||
.endm
|
||||
|
||||
|
||||
.macro preload_leading_step1 bpp, ptr, base
|
||||
/* If the destination is already 16-byte aligned, then we need to preload
|
||||
* between 0 and prefetch_distance (inclusive) cache lines ahead so there
|
||||
* are no gaps when the inner loop starts.
|
||||
*/
|
||||
.if bpp > 0
|
||||
PF bic, ptr, base, #31
|
||||
.set OFFSET, 0
|
||||
.rept prefetch_distance+1
|
||||
PF pld, [ptr, #OFFSET]
|
||||
.set OFFSET, OFFSET+32
|
||||
.endr
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro preload_leading_step2 bpp, bpp_shift, ptr, base
|
||||
/* However, if the destination is not 16-byte aligned, we may need to
|
||||
* preload more cache lines than that. The question we need to ask is:
|
||||
* are the bytes corresponding to the leading pixels more than the amount
|
||||
* by which the source pointer will be rounded down for preloading, and if
|
||||
* so, by how many cache lines? Effectively, we want to calculate
|
||||
* leading_bytes = ((-dst)&15)*src_bpp/dst_bpp
|
||||
* inner_loop_offset = (src+leading_bytes)&31
|
||||
* extra_needed = leading_bytes - inner_loop_offset
|
||||
* and test if extra_needed is <= 0, <= 32, or > 32 (where > 32 is only
|
||||
* possible when there are 4 src bytes for every 1 dst byte).
|
||||
*/
|
||||
.if bpp > 0
|
||||
.ifc base,DST
|
||||
/* The test can be simplified further when preloading the destination */
|
||||
PF tst, base, #16
|
||||
PF beq, 61f
|
||||
.else
|
||||
.if bpp/dst_w_bpp == 4
|
||||
PF add, SCRATCH, base, WK0, lsl #bpp_shift-dst_bpp_shift
|
||||
PF and, SCRATCH, SCRATCH, #31
|
||||
PF rsb, SCRATCH, SCRATCH, WK0, lsl #bpp_shift-dst_bpp_shift
|
||||
PF sub, SCRATCH, SCRATCH, #1 /* so now ranges are -16..-1 / 0..31 / 32..63 */
|
||||
PF movs, SCRATCH, SCRATCH, #32-6 /* so this sets NC / nc / Nc */
|
||||
PF bcs, 61f
|
||||
PF bpl, 60f
|
||||
PF pld, [ptr, #32*(prefetch_distance+2)]
|
||||
.else
|
||||
PF mov, SCRATCH, base, lsl #32-5
|
||||
PF add, SCRATCH, SCRATCH, WK0, lsl #32-5+bpp_shift-dst_bpp_shift
|
||||
PF rsbs, SCRATCH, SCRATCH, WK0, lsl #32-5+bpp_shift-dst_bpp_shift
|
||||
PF bls, 61f
|
||||
.endif
|
||||
.endif
|
||||
60: PF pld, [ptr, #32*(prefetch_distance+1)]
|
||||
61:
|
||||
.endif
|
||||
.endm
|
||||
|
||||
#define IS_END_OF_GROUP(INDEX,SIZE) ((SIZE) < 2 || ((INDEX) & ~((INDEX)+1)) & ((SIZE)/2))
|
||||
.macro preload_middle bpp, base, scratch_holds_offset
|
||||
.if bpp > 0
|
||||
/* prefetch distance = 256/bpp, stm distance = 128/dst_w_bpp */
|
||||
.if IS_END_OF_GROUP(SUBBLOCK,256/128*dst_w_bpp/bpp)
|
||||
.if scratch_holds_offset
|
||||
PF pld, [base, SCRATCH]
|
||||
.else
|
||||
PF bic, SCRATCH, base, #31
|
||||
PF pld, [SCRATCH, #32*prefetch_distance]
|
||||
.endif
|
||||
.endif
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro preload_trailing bpp, bpp_shift, base
|
||||
.if bpp > 0
|
||||
.if bpp*pix_per_block > 256
|
||||
/* Calculations are more complex if more than one fetch per block */
|
||||
PF and, WK1, base, #31
|
||||
PF add, WK1, WK1, WK0, lsl #bpp_shift
|
||||
PF add, WK1, WK1, #32*(bpp*pix_per_block/256-1)*(prefetch_distance+1)
|
||||
PF bic, SCRATCH, base, #31
|
||||
80: PF pld, [SCRATCH, #32*(prefetch_distance+1)]
|
||||
PF add, SCRATCH, SCRATCH, #32
|
||||
PF subs, WK1, WK1, #32
|
||||
PF bhi, 80b
|
||||
.else
|
||||
/* If exactly one fetch per block, then we need either 0, 1 or 2 extra preloads */
|
||||
PF mov, SCRATCH, base, lsl #32-5
|
||||
PF adds, SCRATCH, SCRATCH, X, lsl #32-5+bpp_shift
|
||||
PF adceqs, SCRATCH, SCRATCH, #0
|
||||
/* The instruction above has two effects: ensures Z is only
|
||||
* set if C was clear (so Z indicates that both shifted quantities
|
||||
* were 0), and clears C if Z was set (so C indicates that the sum
|
||||
* of the shifted quantities was greater and not equal to 32) */
|
||||
PF beq, 82f
|
||||
PF bic, SCRATCH, base, #31
|
||||
PF bcc, 81f
|
||||
PF pld, [SCRATCH, #32*(prefetch_distance+2)]
|
||||
81: PF pld, [SCRATCH, #32*(prefetch_distance+1)]
|
||||
82:
|
||||
.endif
|
||||
.endif
|
||||
.endm
|
||||
|
||||
|
||||
.macro preload_line narrow_case, bpp, bpp_shift, base
|
||||
/* "narrow_case" - just means that the macro was invoked from the "narrow"
|
||||
* code path rather than the "medium" one - because in the narrow case,
|
||||
* the row of pixels is known to output no more than 30 bytes, then
|
||||
* (assuming the source pixels are no wider than the the destination
|
||||
* pixels) they cannot possibly straddle more than 2 32-byte cachelines,
|
||||
* meaning there's no need for a loop.
|
||||
* "bpp" - number of bits per pixel in the channel (source, mask or
|
||||
* destination) that's being preloaded, or 0 if this channel is not used
|
||||
* for reading
|
||||
* "bpp_shift" - log2 of ("bpp"/8) (except if "bpp"=0 of course)
|
||||
* "base" - base address register of channel to preload (SRC, MASK or DST)
|
||||
*/
|
||||
.if bpp > 0
|
||||
.if narrow_case && (bpp <= dst_w_bpp)
|
||||
/* In these cases, each line for each channel is in either 1 or 2 cache lines */
|
||||
PF bic, WK0, base, #31
|
||||
PF pld, [WK0]
|
||||
PF add, WK1, base, X, LSL #bpp_shift
|
||||
PF sub, WK1, WK1, #1
|
||||
PF bic, WK1, WK1, #31
|
||||
PF cmp, WK1, WK0
|
||||
PF beq, 90f
|
||||
PF pld, [WK1]
|
||||
90:
|
||||
.else
|
||||
PF bic, WK0, base, #31
|
||||
PF pld, [WK0]
|
||||
PF add, WK1, base, X, lsl #bpp_shift
|
||||
PF sub, WK1, WK1, #1
|
||||
PF bic, WK1, WK1, #31
|
||||
PF cmp, WK1, WK0
|
||||
PF beq, 92f
|
||||
91: PF add, WK0, WK0, #32
|
||||
PF cmp, WK0, WK1
|
||||
PF pld, [WK0]
|
||||
PF bne, 91b
|
||||
92:
|
||||
.endif
|
||||
.endif
|
||||
.endm
|
||||
|
||||
|
||||
.macro conditional_process1_helper cond, process_head, process_tail, numbytes, firstreg, unaligned_src, unaligned_mask, decrementx
|
||||
process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, 0
|
||||
.if decrementx
|
||||
sub&cond X, X, #8*numbytes/dst_w_bpp
|
||||
.endif
|
||||
process_tail cond, numbytes, firstreg
|
||||
.if !((flags) & FLAG_PROCESS_DOES_STORE)
|
||||
pixst cond, numbytes, firstreg, DST
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro conditional_process1 cond, process_head, process_tail, numbytes, firstreg, unaligned_src, unaligned_mask, decrementx
|
||||
.if (flags) & FLAG_BRANCH_OVER
|
||||
.ifc cond,mi
|
||||
bpl 100f
|
||||
.endif
|
||||
.ifc cond,cs
|
||||
bcc 100f
|
||||
.endif
|
||||
.ifc cond,ne
|
||||
beq 100f
|
||||
.endif
|
||||
conditional_process1_helper , process_head, process_tail, numbytes, firstreg, unaligned_src, unaligned_mask, decrementx
|
||||
100:
|
||||
.else
|
||||
conditional_process1_helper cond, process_head, process_tail, numbytes, firstreg, unaligned_src, unaligned_mask, decrementx
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro conditional_process2 test, cond1, cond2, process_head, process_tail, numbytes1, numbytes2, firstreg1, firstreg2, unaligned_src, unaligned_mask, decrementx
|
||||
.if (flags) & (FLAG_DST_READWRITE | FLAG_BRANCH_OVER | FLAG_PROCESS_CORRUPTS_PSR | FLAG_PROCESS_DOES_STORE)
|
||||
/* Can't interleave reads and writes */
|
||||
test
|
||||
conditional_process1 cond1, process_head, process_tail, numbytes1, firstreg1, unaligned_src, unaligned_mask, decrementx
|
||||
.if (flags) & FLAG_PROCESS_CORRUPTS_PSR
|
||||
test
|
||||
.endif
|
||||
conditional_process1 cond2, process_head, process_tail, numbytes2, firstreg2, unaligned_src, unaligned_mask, decrementx
|
||||
.else
|
||||
/* Can interleave reads and writes for better scheduling */
|
||||
test
|
||||
process_head cond1, numbytes1, firstreg1, unaligned_src, unaligned_mask, 0
|
||||
process_head cond2, numbytes2, firstreg2, unaligned_src, unaligned_mask, 0
|
||||
.if decrementx
|
||||
sub&cond1 X, X, #8*numbytes1/dst_w_bpp
|
||||
sub&cond2 X, X, #8*numbytes2/dst_w_bpp
|
||||
.endif
|
||||
process_tail cond1, numbytes1, firstreg1
|
||||
process_tail cond2, numbytes2, firstreg2
|
||||
pixst cond1, numbytes1, firstreg1, DST
|
||||
pixst cond2, numbytes2, firstreg2, DST
|
||||
.endif
|
||||
.endm
|
||||
|
||||
|
||||
.macro test_bits_1_0_ptr
|
||||
movs SCRATCH, WK0, lsl #32-1 /* C,N = bits 1,0 of DST */
|
||||
.endm
|
||||
|
||||
.macro test_bits_3_2_ptr
|
||||
movs SCRATCH, WK0, lsl #32-3 /* C,N = bits 3, 2 of DST */
|
||||
.endm
|
||||
|
||||
.macro leading_15bytes process_head, process_tail
|
||||
/* On entry, WK0 bits 0-3 = number of bytes until destination is 16-byte aligned */
|
||||
/* Use unaligned loads in all cases for simplicity */
|
||||
.if dst_w_bpp == 8
|
||||
conditional_process2 test_bits_1_0_ptr, mi, cs, process_head, process_tail, 1, 2, 1, 2, 1, 1, 1
|
||||
.elseif dst_w_bpp == 16
|
||||
test_bits_1_0_ptr
|
||||
conditional_process1 cs, process_head, process_tail, 2, 2, 1, 1, 1
|
||||
.endif
|
||||
conditional_process2 test_bits_3_2_ptr, mi, cs, process_head, process_tail, 4, 8, 1, 2, 1, 1, 1
|
||||
.endm
|
||||
|
||||
.macro test_bits_3_2_pix
|
||||
movs SCRATCH, X, lsl #dst_bpp_shift+32-3
|
||||
.endm
|
||||
|
||||
.macro test_bits_1_0_pix
|
||||
.if dst_w_bpp == 8
|
||||
movs SCRATCH, X, lsl #dst_bpp_shift+32-1
|
||||
.else
|
||||
movs SCRATCH, X, lsr #1
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro trailing_15bytes process_head, process_tail, unaligned_src, unaligned_mask
|
||||
conditional_process2 test_bits_3_2_pix, cs, mi, process_head, process_tail, 8, 4, 0, 2, unaligned_src, unaligned_mask, 0
|
||||
.if dst_w_bpp == 16
|
||||
test_bits_1_0_pix
|
||||
conditional_process1 cs, process_head, process_tail, 2, 0, unaligned_src, unaligned_mask, 0
|
||||
.elseif dst_w_bpp == 8
|
||||
conditional_process2 test_bits_1_0_pix, cs, mi, process_head, process_tail, 2, 1, 0, 1, unaligned_src, unaligned_mask, 0
|
||||
.endif
|
||||
.endm
|
||||
|
||||
|
||||
.macro wide_case_inner_loop process_head, process_tail, unaligned_src, unaligned_mask, dst_alignment
|
||||
110:
|
||||
.set SUBBLOCK, 0 /* this is a count of STMs; there can be up to 8 STMs per block */
|
||||
.rept pix_per_block*dst_w_bpp/128
|
||||
process_head , 16, 0, unaligned_src, unaligned_mask, 1
|
||||
.if (src_bpp > 0) && (mask_bpp == 0) && ((flags) & FLAG_PROCESS_PRESERVES_SCRATCH)
|
||||
preload_middle src_bpp, SRC, 1
|
||||
.elseif (src_bpp == 0) && (mask_bpp > 0) && ((flags) & FLAG_PROCESS_PRESERVES_SCRATCH)
|
||||
preload_middle mask_bpp, MASK, 1
|
||||
.else
|
||||
preload_middle src_bpp, SRC, 0
|
||||
preload_middle mask_bpp, MASK, 0
|
||||
.endif
|
||||
.if (dst_r_bpp > 0) && ((SUBBLOCK % 2) == 0)
|
||||
/* Because we know that writes are 16-byte aligned, it's relatively easy to ensure that
|
||||
* destination prefetches are 32-byte aligned. It's also the easiest channel to offset
|
||||
* preloads for, to achieve staggered prefetches for multiple channels, because there are
|
||||
* always two STMs per prefetch, so there is always an opposite STM on which to put the
|
||||
* preload. Note, no need to BIC the base register here */
|
||||
PF pld, [DST, #32*prefetch_distance - dst_alignment]
|
||||
.endif
|
||||
process_tail , 16, 0
|
||||
.if !((flags) & FLAG_PROCESS_DOES_STORE)
|
||||
pixst , 16, 0, DST
|
||||
.endif
|
||||
.set SUBBLOCK, SUBBLOCK+1
|
||||
.endr
|
||||
subs X, X, #pix_per_block
|
||||
bhs 110b
|
||||
.endm
|
||||
|
||||
.macro wide_case_inner_loop_and_trailing_pixels process_head, process_tail, process_inner_loop, exit_label, unaligned_src, unaligned_mask
|
||||
/* Destination now 16-byte aligned; we have at least one block before we have to stop preloading */
|
||||
.if dst_r_bpp > 0
|
||||
tst DST, #16
|
||||
bne 111f
|
||||
process_inner_loop process_head, process_tail, unaligned_src, unaligned_mask, 16
|
||||
b 112f
|
||||
111:
|
||||
.endif
|
||||
process_inner_loop process_head, process_tail, unaligned_src, unaligned_mask, 0
|
||||
112:
|
||||
/* Just before the final (prefetch_distance+1) 32-byte blocks, deal with final preloads */
|
||||
.if (src_bpp*pix_per_block > 256) || (mask_bpp*pix_per_block > 256) || (dst_r_bpp*pix_per_block > 256)
|
||||
PF and, WK0, X, #pix_per_block-1
|
||||
.endif
|
||||
preload_trailing src_bpp, src_bpp_shift, SRC
|
||||
preload_trailing mask_bpp, mask_bpp_shift, MASK
|
||||
preload_trailing dst_r_bpp, dst_bpp_shift, DST
|
||||
add X, X, #(prefetch_distance+2)*pix_per_block - 128/dst_w_bpp
|
||||
/* The remainder of the line is handled identically to the medium case */
|
||||
medium_case_inner_loop_and_trailing_pixels process_head, process_tail,, exit_label, unaligned_src, unaligned_mask
|
||||
.endm
|
||||
|
||||
.macro medium_case_inner_loop_and_trailing_pixels process_head, process_tail, unused, exit_label, unaligned_src, unaligned_mask
|
||||
120:
|
||||
process_head , 16, 0, unaligned_src, unaligned_mask, 0
|
||||
process_tail , 16, 0
|
||||
.if !((flags) & FLAG_PROCESS_DOES_STORE)
|
||||
pixst , 16, 0, DST
|
||||
.endif
|
||||
subs X, X, #128/dst_w_bpp
|
||||
bhs 120b
|
||||
/* Trailing pixels */
|
||||
tst X, #128/dst_w_bpp - 1
|
||||
beq exit_label
|
||||
trailing_15bytes process_head, process_tail, unaligned_src, unaligned_mask
|
||||
.endm
|
||||
|
||||
.macro narrow_case_inner_loop_and_trailing_pixels process_head, process_tail, unused, exit_label, unaligned_src, unaligned_mask
|
||||
tst X, #16*8/dst_w_bpp
|
||||
conditional_process1 ne, process_head, process_tail, 16, 0, unaligned_src, unaligned_mask, 0
|
||||
/* Trailing pixels */
|
||||
/* In narrow case, it's relatively unlikely to be aligned, so let's do without a branch here */
|
||||
trailing_15bytes process_head, process_tail, unaligned_src, unaligned_mask
|
||||
.endm
|
||||
|
||||
.macro switch_on_alignment action, process_head, process_tail, process_inner_loop, exit_label
|
||||
/* Note that if we're reading the destination, it's already guaranteed to be aligned at this point */
|
||||
.if mask_bpp == 8 || mask_bpp == 16
|
||||
tst MASK, #3
|
||||
bne 141f
|
||||
.endif
|
||||
.if src_bpp == 8 || src_bpp == 16
|
||||
tst SRC, #3
|
||||
bne 140f
|
||||
.endif
|
||||
action process_head, process_tail, process_inner_loop, exit_label, 0, 0
|
||||
.if src_bpp == 8 || src_bpp == 16
|
||||
b exit_label
|
||||
140:
|
||||
action process_head, process_tail, process_inner_loop, exit_label, 1, 0
|
||||
.endif
|
||||
.if mask_bpp == 8 || mask_bpp == 16
|
||||
b exit_label
|
||||
141:
|
||||
.if src_bpp == 8 || src_bpp == 16
|
||||
tst SRC, #3
|
||||
bne 142f
|
||||
.endif
|
||||
action process_head, process_tail, process_inner_loop, exit_label, 0, 1
|
||||
.if src_bpp == 8 || src_bpp == 16
|
||||
b exit_label
|
||||
142:
|
||||
action process_head, process_tail, process_inner_loop, exit_label, 1, 1
|
||||
.endif
|
||||
.endif
|
||||
.endm
|
||||
|
||||
|
||||
.macro end_of_line restore_x, vars_spilled, loop_label, last_one
|
||||
.if vars_spilled
|
||||
/* Sadly, GAS doesn't seem have an equivalent of the DCI directive? */
|
||||
/* This is ldmia sp,{} */
|
||||
.word 0xE89D0000 | LINE_SAVED_REGS
|
||||
.endif
|
||||
subs Y, Y, #1
|
||||
.if vars_spilled
|
||||
.if (LINE_SAVED_REGS) & (1<<1)
|
||||
str Y, [sp]
|
||||
.endif
|
||||
.endif
|
||||
add DST, DST, STRIDE_D
|
||||
.if src_bpp > 0
|
||||
add SRC, SRC, STRIDE_S
|
||||
.endif
|
||||
.if mask_bpp > 0
|
||||
add MASK, MASK, STRIDE_M
|
||||
.endif
|
||||
.if restore_x
|
||||
mov X, ORIG_W
|
||||
.endif
|
||||
bhs loop_label
|
||||
.ifc "last_one",""
|
||||
.if vars_spilled
|
||||
b 197f
|
||||
.else
|
||||
b 198f
|
||||
.endif
|
||||
.else
|
||||
.if (!vars_spilled) && ((flags) & FLAG_SPILL_LINE_VARS)
|
||||
b 198f
|
||||
.endif
|
||||
.endif
|
||||
.endm
|
||||
|
||||
|
||||
.macro generate_composite_function fname, \
|
||||
src_bpp_, \
|
||||
mask_bpp_, \
|
||||
dst_w_bpp_, \
|
||||
flags_, \
|
||||
prefetch_distance_, \
|
||||
init, \
|
||||
newline, \
|
||||
cleanup, \
|
||||
process_head, \
|
||||
process_tail, \
|
||||
process_inner_loop
|
||||
|
||||
.func fname
|
||||
.global fname
|
||||
/* For ELF format also set function visibility to hidden */
|
||||
#ifdef __ELF__
|
||||
.hidden fname
|
||||
.type fname, %function
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Make some macro arguments globally visible and accessible
|
||||
* from other macros
|
||||
*/
|
||||
.set src_bpp, src_bpp_
|
||||
.set mask_bpp, mask_bpp_
|
||||
.set dst_w_bpp, dst_w_bpp_
|
||||
.set flags, flags_
|
||||
.set prefetch_distance, prefetch_distance_
|
||||
|
||||
/*
|
||||
* Select prefetch type for this function.
|
||||
*/
|
||||
.if prefetch_distance == 0
|
||||
.set PREFETCH_TYPE_CURRENT, PREFETCH_TYPE_NONE
|
||||
.else
|
||||
.set PREFETCH_TYPE_CURRENT, PREFETCH_TYPE_STANDARD
|
||||
.endif
|
||||
|
||||
.if src_bpp == 32
|
||||
.set src_bpp_shift, 2
|
||||
.elseif src_bpp == 24
|
||||
.set src_bpp_shift, 0
|
||||
.elseif src_bpp == 16
|
||||
.set src_bpp_shift, 1
|
||||
.elseif src_bpp == 8
|
||||
.set src_bpp_shift, 0
|
||||
.elseif src_bpp == 0
|
||||
.set src_bpp_shift, -1
|
||||
.else
|
||||
.error "requested src bpp (src_bpp) is not supported"
|
||||
.endif
|
||||
|
||||
.if mask_bpp == 32
|
||||
.set mask_bpp_shift, 2
|
||||
.elseif mask_bpp == 24
|
||||
.set mask_bpp_shift, 0
|
||||
.elseif mask_bpp == 8
|
||||
.set mask_bpp_shift, 0
|
||||
.elseif mask_bpp == 0
|
||||
.set mask_bpp_shift, -1
|
||||
.else
|
||||
.error "requested mask bpp (mask_bpp) is not supported"
|
||||
.endif
|
||||
|
||||
.if dst_w_bpp == 32
|
||||
.set dst_bpp_shift, 2
|
||||
.elseif dst_w_bpp == 24
|
||||
.set dst_bpp_shift, 0
|
||||
.elseif dst_w_bpp == 16
|
||||
.set dst_bpp_shift, 1
|
||||
.elseif dst_w_bpp == 8
|
||||
.set dst_bpp_shift, 0
|
||||
.else
|
||||
.error "requested dst bpp (dst_w_bpp) is not supported"
|
||||
.endif
|
||||
|
||||
.if (((flags) & FLAG_DST_READWRITE) != 0)
|
||||
.set dst_r_bpp, dst_w_bpp
|
||||
.else
|
||||
.set dst_r_bpp, 0
|
||||
.endif
|
||||
|
||||
.set pix_per_block, 16*8/dst_w_bpp
|
||||
.if src_bpp != 0
|
||||
.if 32*8/src_bpp > pix_per_block
|
||||
.set pix_per_block, 32*8/src_bpp
|
||||
.endif
|
||||
.endif
|
||||
.if mask_bpp != 0
|
||||
.if 32*8/mask_bpp > pix_per_block
|
||||
.set pix_per_block, 32*8/mask_bpp
|
||||
.endif
|
||||
.endif
|
||||
.if dst_r_bpp != 0
|
||||
.if 32*8/dst_r_bpp > pix_per_block
|
||||
.set pix_per_block, 32*8/dst_r_bpp
|
||||
.endif
|
||||
.endif
|
||||
|
||||
/* The standard entry conditions set up by pixman-arm-common.h are:
|
||||
* r0 = width (pixels)
|
||||
* r1 = height (rows)
|
||||
* r2 = pointer to top-left pixel of destination
|
||||
* r3 = destination stride (pixels)
|
||||
* [sp] = source pixel value, or pointer to top-left pixel of source
|
||||
* [sp,#4] = 0 or source stride (pixels)
|
||||
* The following arguments are unused for non-mask operations
|
||||
* [sp,#8] = mask pixel value, or pointer to top-left pixel of mask
|
||||
* [sp,#12] = 0 or mask stride (pixels)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Assign symbolic names to registers
|
||||
*/
|
||||
X .req r0 /* pixels to go on this line */
|
||||
Y .req r1 /* lines to go */
|
||||
DST .req r2 /* destination pixel pointer */
|
||||
STRIDE_D .req r3 /* destination stride (bytes, minus width) */
|
||||
SRC .req r4 /* source pixel pointer */
|
||||
STRIDE_S .req r5 /* source stride (bytes, minus width) */
|
||||
MASK .req r6 /* mask pixel pointer (if applicable) */
|
||||
STRIDE_M .req r7 /* mask stride (bytes, minus width) */
|
||||
WK0 .req r8 /* pixel data registers */
|
||||
WK1 .req r9
|
||||
WK2 .req r10
|
||||
WK3 .req r11
|
||||
SCRATCH .req r12
|
||||
ORIG_W .req r14 /* width (pixels) */
|
||||
|
||||
fname:
|
||||
.fnstart
|
||||
.save {r4-r11, lr}
|
||||
push {r4-r11, lr} /* save all registers */
|
||||
|
||||
subs Y, Y, #1
|
||||
blo 199f
|
||||
|
||||
#ifdef DEBUG_PARAMS
|
||||
.pad #9*4
|
||||
sub sp, sp, #9*4
|
||||
#endif
|
||||
|
||||
.if src_bpp > 0
|
||||
ldr SRC, [sp, #ARGS_STACK_OFFSET]
|
||||
ldr STRIDE_S, [sp, #ARGS_STACK_OFFSET+4]
|
||||
.endif
|
||||
.if mask_bpp > 0
|
||||
ldr MASK, [sp, #ARGS_STACK_OFFSET+8]
|
||||
ldr STRIDE_M, [sp, #ARGS_STACK_OFFSET+12]
|
||||
.endif
|
||||
|
||||
#ifdef DEBUG_PARAMS
|
||||
add Y, Y, #1
|
||||
stmia sp, {r0-r7,pc}
|
||||
sub Y, Y, #1
|
||||
#endif
|
||||
|
||||
init
|
||||
|
||||
lsl STRIDE_D, #dst_bpp_shift /* stride in bytes */
|
||||
sub STRIDE_D, STRIDE_D, X, lsl #dst_bpp_shift
|
||||
.if src_bpp > 0
|
||||
lsl STRIDE_S, #src_bpp_shift
|
||||
sub STRIDE_S, STRIDE_S, X, lsl #src_bpp_shift
|
||||
.endif
|
||||
.if mask_bpp > 0
|
||||
lsl STRIDE_M, #mask_bpp_shift
|
||||
sub STRIDE_M, STRIDE_M, X, lsl #mask_bpp_shift
|
||||
.endif
|
||||
|
||||
/* Are we not even wide enough to have one 16-byte aligned 16-byte block write? */
|
||||
cmp X, #2*16*8/dst_w_bpp - 1
|
||||
blo 170f
|
||||
.if src_bpp || mask_bpp || dst_r_bpp /* Wide and medium cases are the same for fill */
|
||||
/* To preload ahead on the current line, we need at least (prefetch_distance+2) 32-byte blocks on all prefetch channels */
|
||||
cmp X, #(prefetch_distance+3)*pix_per_block - 1
|
||||
blo 160f
|
||||
|
||||
/* Wide case */
|
||||
/* Adjust X so that the decrement instruction can also test for
|
||||
* inner loop termination. We want it to stop when there are
|
||||
* (prefetch_distance+1) complete blocks to go. */
|
||||
sub X, X, #(prefetch_distance+2)*pix_per_block
|
||||
mov ORIG_W, X
|
||||
.if (flags) & FLAG_SPILL_LINE_VARS_WIDE
|
||||
/* This is stmdb sp!,{} */
|
||||
.word 0xE92D0000 | LINE_SAVED_REGS
|
||||
.endif
|
||||
151: /* New line */
|
||||
newline
|
||||
preload_leading_step1 src_bpp, WK1, SRC
|
||||
preload_leading_step1 mask_bpp, WK2, MASK
|
||||
preload_leading_step1 dst_r_bpp, WK3, DST
|
||||
|
||||
tst DST, #15
|
||||
beq 154f
|
||||
rsb WK0, DST, #0 /* bits 0-3 = number of leading bytes until destination aligned */
|
||||
.if (src_bpp != 0 && src_bpp != 2*dst_w_bpp) || (mask_bpp != 0 && mask_bpp != 2*dst_w_bpp)
|
||||
PF and, WK0, WK0, #15
|
||||
.endif
|
||||
|
||||
preload_leading_step2 src_bpp, src_bpp_shift, WK1, SRC
|
||||
preload_leading_step2 mask_bpp, mask_bpp_shift, WK2, MASK
|
||||
preload_leading_step2 dst_r_bpp, dst_bpp_shift, WK3, DST
|
||||
|
||||
leading_15bytes process_head, process_tail
|
||||
|
||||
154: /* Destination now 16-byte aligned; we have at least one prefetch on each channel as well as at least one 16-byte output block */
|
||||
.if (src_bpp > 0) && (mask_bpp == 0) && ((flags) & FLAG_PROCESS_PRESERVES_SCRATCH)
|
||||
and SCRATCH, SRC, #31
|
||||
rsb SCRATCH, SCRATCH, #32*prefetch_distance
|
||||
.elseif (src_bpp == 0) && (mask_bpp > 0) && ((flags) & FLAG_PROCESS_PRESERVES_SCRATCH)
|
||||
and SCRATCH, MASK, #31
|
||||
rsb SCRATCH, SCRATCH, #32*prefetch_distance
|
||||
.endif
|
||||
.ifc "process_inner_loop",""
|
||||
switch_on_alignment wide_case_inner_loop_and_trailing_pixels, process_head, process_tail, wide_case_inner_loop, 157f
|
||||
.else
|
||||
switch_on_alignment wide_case_inner_loop_and_trailing_pixels, process_head, process_tail, process_inner_loop, 157f
|
||||
.endif
|
||||
|
||||
157: /* Check for another line */
|
||||
end_of_line 1, %((flags) & FLAG_SPILL_LINE_VARS_WIDE), 151b
|
||||
.endif
|
||||
|
||||
.ltorg
|
||||
|
||||
160: /* Medium case */
|
||||
mov ORIG_W, X
|
||||
.if (flags) & FLAG_SPILL_LINE_VARS_NON_WIDE
|
||||
/* This is stmdb sp!,{} */
|
||||
.word 0xE92D0000 | LINE_SAVED_REGS
|
||||
.endif
|
||||
161: /* New line */
|
||||
newline
|
||||
preload_line 0, src_bpp, src_bpp_shift, SRC /* in: X, corrupts: WK0-WK1 */
|
||||
preload_line 0, mask_bpp, mask_bpp_shift, MASK
|
||||
preload_line 0, dst_r_bpp, dst_bpp_shift, DST
|
||||
|
||||
sub X, X, #128/dst_w_bpp /* simplifies inner loop termination */
|
||||
tst DST, #15
|
||||
beq 164f
|
||||
rsb WK0, DST, #0 /* bits 0-3 = number of leading bytes until destination aligned */
|
||||
|
||||
leading_15bytes process_head, process_tail
|
||||
|
||||
164: /* Destination now 16-byte aligned; we have at least one 16-byte output block */
|
||||
switch_on_alignment medium_case_inner_loop_and_trailing_pixels, process_head, process_tail,, 167f
|
||||
|
||||
167: /* Check for another line */
|
||||
end_of_line 1, %((flags) & FLAG_SPILL_LINE_VARS_NON_WIDE), 161b
|
||||
|
||||
.ltorg
|
||||
|
||||
170: /* Narrow case, less than 31 bytes, so no guarantee of at least one 16-byte block */
|
||||
.if dst_w_bpp < 32
|
||||
mov ORIG_W, X
|
||||
.endif
|
||||
.if (flags) & FLAG_SPILL_LINE_VARS_NON_WIDE
|
||||
/* This is stmdb sp!,{} */
|
||||
.word 0xE92D0000 | LINE_SAVED_REGS
|
||||
.endif
|
||||
171: /* New line */
|
||||
newline
|
||||
preload_line 1, src_bpp, src_bpp_shift, SRC /* in: X, corrupts: WK0-WK1 */
|
||||
preload_line 1, mask_bpp, mask_bpp_shift, MASK
|
||||
preload_line 1, dst_r_bpp, dst_bpp_shift, DST
|
||||
|
||||
.if dst_w_bpp == 8
|
||||
tst DST, #3
|
||||
beq 174f
|
||||
172: subs X, X, #1
|
||||
blo 177f
|
||||
process_head , 1, 0, 1, 1, 0
|
||||
process_tail , 1, 0
|
||||
.if !((flags) & FLAG_PROCESS_DOES_STORE)
|
||||
pixst , 1, 0, DST
|
||||
.endif
|
||||
tst DST, #3
|
||||
bne 172b
|
||||
.elseif dst_w_bpp == 16
|
||||
tst DST, #2
|
||||
beq 174f
|
||||
subs X, X, #1
|
||||
blo 177f
|
||||
process_head , 2, 0, 1, 1, 0
|
||||
process_tail , 2, 0
|
||||
.if !((flags) & FLAG_PROCESS_DOES_STORE)
|
||||
pixst , 2, 0, DST
|
||||
.endif
|
||||
.endif
|
||||
|
||||
174: /* Destination now 4-byte aligned; we have 0 or more output bytes to go */
|
||||
switch_on_alignment narrow_case_inner_loop_and_trailing_pixels, process_head, process_tail,, 177f
|
||||
|
||||
177: /* Check for another line */
|
||||
end_of_line %(dst_w_bpp < 32), %((flags) & FLAG_SPILL_LINE_VARS_NON_WIDE), 171b, last_one
|
||||
|
||||
197:
|
||||
.if (flags) & FLAG_SPILL_LINE_VARS
|
||||
add sp, sp, #LINE_SAVED_REG_COUNT*4
|
||||
.endif
|
||||
198:
|
||||
cleanup
|
||||
|
||||
#ifdef DEBUG_PARAMS
|
||||
add sp, sp, #9*4 /* junk the debug copy of arguments */
|
||||
#endif
|
||||
199:
|
||||
pop {r4-r11, pc} /* exit */
|
||||
.fnend
|
||||
|
||||
.ltorg
|
||||
|
||||
.unreq X
|
||||
.unreq Y
|
||||
.unreq DST
|
||||
.unreq STRIDE_D
|
||||
.unreq SRC
|
||||
.unreq STRIDE_S
|
||||
.unreq MASK
|
||||
.unreq STRIDE_M
|
||||
.unreq WK0
|
||||
.unreq WK1
|
||||
.unreq WK2
|
||||
.unreq WK3
|
||||
.unreq SCRATCH
|
||||
.unreq ORIG_W
|
||||
.endfunc
|
||||
.endm
|
||||
|
||||
.macro line_saved_regs x:vararg
|
||||
.set LINE_SAVED_REGS, 0
|
||||
.set LINE_SAVED_REG_COUNT, 0
|
||||
.irp SAVED_REG,x
|
||||
.ifc "SAVED_REG","Y"
|
||||
.set LINE_SAVED_REGS, LINE_SAVED_REGS | (1<<1)
|
||||
.set LINE_SAVED_REG_COUNT, LINE_SAVED_REG_COUNT + 1
|
||||
.endif
|
||||
.ifc "SAVED_REG","STRIDE_D"
|
||||
.set LINE_SAVED_REGS, LINE_SAVED_REGS | (1<<3)
|
||||
.set LINE_SAVED_REG_COUNT, LINE_SAVED_REG_COUNT + 1
|
||||
.endif
|
||||
.ifc "SAVED_REG","STRIDE_S"
|
||||
.set LINE_SAVED_REGS, LINE_SAVED_REGS | (1<<5)
|
||||
.set LINE_SAVED_REG_COUNT, LINE_SAVED_REG_COUNT + 1
|
||||
.endif
|
||||
.ifc "SAVED_REG","STRIDE_M"
|
||||
.set LINE_SAVED_REGS, LINE_SAVED_REGS | (1<<7)
|
||||
.set LINE_SAVED_REG_COUNT, LINE_SAVED_REG_COUNT + 1
|
||||
.endif
|
||||
.ifc "SAVED_REG","ORIG_W"
|
||||
.set LINE_SAVED_REGS, LINE_SAVED_REGS | (1<<14)
|
||||
.set LINE_SAVED_REG_COUNT, LINE_SAVED_REG_COUNT + 1
|
||||
.endif
|
||||
.endr
|
||||
.endm
|
||||
|
||||
.macro nop_macro x:vararg
|
||||
.endm
|
||||
257
gfx/cairo/libpixman/src/pixman-arm-simd.c
Normal file
257
gfx/cairo/libpixman/src/pixman-arm-simd.c
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
/*
|
||||
* Copyright © 2008 Mozilla Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Mozilla Corporation not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Mozilla Corporation makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Author: Jeff Muizelaar (jeff@infidigm.net)
|
||||
*
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "pixman-private.h"
|
||||
#include "pixman-arm-common.h"
|
||||
#include "pixman-inlines.h"
|
||||
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, src_8888_8888,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, src_x888_8888,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, src_0565_0565,
|
||||
uint16_t, 1, uint16_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, src_8_8,
|
||||
uint8_t, 1, uint8_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, src_0565_8888,
|
||||
uint16_t, 1, uint32_t, 1)
|
||||
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, add_8_8,
|
||||
uint8_t, 1, uint8_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, over_8888_8888,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, armv6, over_8888_n_8888,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
|
||||
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, armv6, over_n_8_8888,
|
||||
uint8_t, 1, uint32_t, 1)
|
||||
|
||||
PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST (armv6, 0565_0565, SRC,
|
||||
uint16_t, uint16_t)
|
||||
PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST (armv6, 8888_8888, SRC,
|
||||
uint32_t, uint32_t)
|
||||
|
||||
void
|
||||
pixman_composite_src_n_8888_asm_armv6 (int32_t w,
|
||||
int32_t h,
|
||||
uint32_t *dst,
|
||||
int32_t dst_stride,
|
||||
uint32_t src);
|
||||
|
||||
void
|
||||
pixman_composite_src_n_0565_asm_armv6 (int32_t w,
|
||||
int32_t h,
|
||||
uint16_t *dst,
|
||||
int32_t dst_stride,
|
||||
uint16_t src);
|
||||
|
||||
void
|
||||
pixman_composite_src_n_8_asm_armv6 (int32_t w,
|
||||
int32_t h,
|
||||
uint8_t *dst,
|
||||
int32_t dst_stride,
|
||||
uint8_t src);
|
||||
|
||||
static pixman_bool_t
|
||||
arm_simd_fill (pixman_implementation_t *imp,
|
||||
uint32_t * bits,
|
||||
int stride, /* in 32-bit words */
|
||||
int bpp,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
uint32_t _xor)
|
||||
{
|
||||
/* stride is always multiple of 32bit units in pixman */
|
||||
uint32_t byte_stride = stride * sizeof(uint32_t);
|
||||
|
||||
switch (bpp)
|
||||
{
|
||||
case 8:
|
||||
pixman_composite_src_n_8_asm_armv6 (
|
||||
width,
|
||||
height,
|
||||
(uint8_t *)(((char *) bits) + y * byte_stride + x),
|
||||
byte_stride,
|
||||
_xor & 0xff);
|
||||
return TRUE;
|
||||
case 16:
|
||||
pixman_composite_src_n_0565_asm_armv6 (
|
||||
width,
|
||||
height,
|
||||
(uint16_t *)(((char *) bits) + y * byte_stride + x * 2),
|
||||
byte_stride / 2,
|
||||
_xor & 0xffff);
|
||||
return TRUE;
|
||||
case 32:
|
||||
pixman_composite_src_n_8888_asm_armv6 (
|
||||
width,
|
||||
height,
|
||||
(uint32_t *)(((char *) bits) + y * byte_stride + x * 4),
|
||||
byte_stride / 4,
|
||||
_xor);
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static pixman_bool_t
|
||||
arm_simd_blt (pixman_implementation_t *imp,
|
||||
uint32_t * src_bits,
|
||||
uint32_t * dst_bits,
|
||||
int src_stride, /* in 32-bit words */
|
||||
int dst_stride, /* in 32-bit words */
|
||||
int src_bpp,
|
||||
int dst_bpp,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dest_x,
|
||||
int dest_y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
if (src_bpp != dst_bpp)
|
||||
return FALSE;
|
||||
|
||||
switch (src_bpp)
|
||||
{
|
||||
case 8:
|
||||
pixman_composite_src_8_8_asm_armv6 (
|
||||
width, height,
|
||||
(uint8_t *)(((char *) dst_bits) +
|
||||
dest_y * dst_stride * 4 + dest_x * 1), dst_stride * 4,
|
||||
(uint8_t *)(((char *) src_bits) +
|
||||
src_y * src_stride * 4 + src_x * 1), src_stride * 4);
|
||||
return TRUE;
|
||||
case 16:
|
||||
pixman_composite_src_0565_0565_asm_armv6 (
|
||||
width, height,
|
||||
(uint16_t *)(((char *) dst_bits) +
|
||||
dest_y * dst_stride * 4 + dest_x * 2), dst_stride * 2,
|
||||
(uint16_t *)(((char *) src_bits) +
|
||||
src_y * src_stride * 4 + src_x * 2), src_stride * 2);
|
||||
return TRUE;
|
||||
case 32:
|
||||
pixman_composite_src_8888_8888_asm_armv6 (
|
||||
width, height,
|
||||
(uint32_t *)(((char *) dst_bits) +
|
||||
dest_y * dst_stride * 4 + dest_x * 4), dst_stride,
|
||||
(uint32_t *)(((char *) src_bits) +
|
||||
src_y * src_stride * 4 + src_x * 4), src_stride);
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static const pixman_fast_path_t arm_simd_fast_paths[] =
|
||||
{
|
||||
PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, a8r8g8b8, armv6_composite_src_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, a8b8g8r8, armv6_composite_src_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, x8r8g8b8, armv6_composite_src_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, x8b8g8r8, armv6_composite_src_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, x8r8g8b8, armv6_composite_src_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, x8b8g8r8, armv6_composite_src_8888_8888),
|
||||
|
||||
PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, a8b8g8r8, armv6_composite_src_x888_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, a8r8g8b8, armv6_composite_src_x888_8888),
|
||||
|
||||
PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, r5g6b5, armv6_composite_src_0565_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, b5g6r5, armv6_composite_src_0565_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a1r5g5b5, null, a1r5g5b5, armv6_composite_src_0565_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a1b5g5r5, null, a1b5g5r5, armv6_composite_src_0565_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a1r5g5b5, null, x1r5g5b5, armv6_composite_src_0565_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a1b5g5r5, null, x1b5g5r5, armv6_composite_src_0565_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, x1r5g5b5, null, x1r5g5b5, armv6_composite_src_0565_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, x1b5g5r5, null, x1b5g5r5, armv6_composite_src_0565_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a4r4g4b4, null, a4r4g4b4, armv6_composite_src_0565_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a4b4g4r4, null, a4b4g4r4, armv6_composite_src_0565_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a4r4g4b4, null, x4r4g4b4, armv6_composite_src_0565_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a4b4g4r4, null, x4b4g4r4, armv6_composite_src_0565_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, x4r4g4b4, null, x4r4g4b4, armv6_composite_src_0565_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, x4b4g4r4, null, x4b4g4r4, armv6_composite_src_0565_0565),
|
||||
|
||||
PIXMAN_STD_FAST_PATH (SRC, a8, null, a8, armv6_composite_src_8_8),
|
||||
PIXMAN_STD_FAST_PATH (SRC, r3g3b2, null, r3g3b2, armv6_composite_src_8_8),
|
||||
PIXMAN_STD_FAST_PATH (SRC, b2g3r3, null, b2g3r3, armv6_composite_src_8_8),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a2r2g2b2, null, a2r2g2b2, armv6_composite_src_8_8),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a2b2g2r2, null, a2b2g2r2, armv6_composite_src_8_8),
|
||||
PIXMAN_STD_FAST_PATH (SRC, c8, null, c8, armv6_composite_src_8_8),
|
||||
PIXMAN_STD_FAST_PATH (SRC, g8, null, g8, armv6_composite_src_8_8),
|
||||
PIXMAN_STD_FAST_PATH (SRC, x4a4, null, x4a4, armv6_composite_src_8_8),
|
||||
PIXMAN_STD_FAST_PATH (SRC, x4c4, null, x4c4, armv6_composite_src_8_8),
|
||||
PIXMAN_STD_FAST_PATH (SRC, x4g4, null, x4g4, armv6_composite_src_8_8),
|
||||
|
||||
PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, a8r8g8b8, armv6_composite_src_0565_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, x8r8g8b8, armv6_composite_src_0565_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, a8b8g8r8, armv6_composite_src_0565_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, x8b8g8r8, armv6_composite_src_0565_8888),
|
||||
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, armv6_composite_over_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, armv6_composite_over_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, armv6_composite_over_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, armv6_composite_over_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, a8r8g8b8, armv6_composite_over_8888_n_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, x8r8g8b8, armv6_composite_over_8888_n_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, solid, a8b8g8r8, armv6_composite_over_8888_n_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, solid, x8b8g8r8, armv6_composite_over_8888_n_8888),
|
||||
|
||||
PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, armv6_composite_add_8_8),
|
||||
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8r8g8b8, armv6_composite_over_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8r8g8b8, armv6_composite_over_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8b8g8r8, armv6_composite_over_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8b8g8r8, armv6_composite_over_n_8_8888),
|
||||
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, r5g6b5, r5g6b5, armv6_0565_0565),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, b5g6r5, b5g6r5, armv6_0565_0565),
|
||||
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, armv6_8888_8888),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, armv6_8888_8888),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, armv6_8888_8888),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, a8b8g8r8, armv6_8888_8888),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, x8b8g8r8, armv6_8888_8888),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, x8b8g8r8, x8b8g8r8, armv6_8888_8888),
|
||||
|
||||
{ PIXMAN_OP_NONE },
|
||||
};
|
||||
|
||||
pixman_implementation_t *
|
||||
_pixman_implementation_create_arm_simd (pixman_implementation_t *fallback)
|
||||
{
|
||||
pixman_implementation_t *imp = _pixman_implementation_create (fallback, arm_simd_fast_paths);
|
||||
|
||||
imp->blt = arm_simd_blt;
|
||||
imp->fill = arm_simd_fill;
|
||||
|
||||
return imp;
|
||||
}
|
||||
229
gfx/cairo/libpixman/src/pixman-arm.c
Normal file
229
gfx/cairo/libpixman/src/pixman-arm.c
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
* Copyright © 2000 SuSE, Inc.
|
||||
* Copyright © 2007 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of SuSE not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. SuSE makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
|
||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "pixman-private.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ARM_V7 = (1 << 0),
|
||||
ARM_V6 = (1 << 1),
|
||||
ARM_VFP = (1 << 2),
|
||||
ARM_NEON = (1 << 3),
|
||||
ARM_IWMMXT = (1 << 4)
|
||||
} arm_cpu_features_t;
|
||||
|
||||
#if defined(USE_ARM_SIMD) || defined(USE_ARM_NEON) || defined(USE_ARM_IWMMXT)
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
/* Needed for EXCEPTION_ILLEGAL_INSTRUCTION */
|
||||
#include <windows.h>
|
||||
|
||||
extern int pixman_msvc_try_arm_neon_op ();
|
||||
extern int pixman_msvc_try_arm_simd_op ();
|
||||
|
||||
static arm_cpu_features_t
|
||||
detect_cpu_features (void)
|
||||
{
|
||||
arm_cpu_features_t features = 0;
|
||||
|
||||
__try
|
||||
{
|
||||
pixman_msvc_try_arm_simd_op ();
|
||||
features |= ARM_V6;
|
||||
}
|
||||
__except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION)
|
||||
{
|
||||
}
|
||||
|
||||
__try
|
||||
{
|
||||
pixman_msvc_try_arm_neon_op ();
|
||||
features |= ARM_NEON;
|
||||
}
|
||||
__except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION)
|
||||
{
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
#elif defined(__APPLE__) && defined(TARGET_OS_IPHONE) /* iOS */
|
||||
|
||||
#include "TargetConditionals.h"
|
||||
|
||||
static arm_cpu_features_t
|
||||
detect_cpu_features (void)
|
||||
{
|
||||
arm_cpu_features_t features = 0;
|
||||
|
||||
features |= ARM_V6;
|
||||
|
||||
/* Detection of ARM NEON on iOS is fairly simple because iOS binaries
|
||||
* contain separate executable images for each processor architecture.
|
||||
* So all we have to do is detect the armv7 architecture build. The
|
||||
* operating system automatically runs the armv7 binary for armv7 devices
|
||||
* and the armv6 binary for armv6 devices.
|
||||
*/
|
||||
#if defined(__ARM_NEON__)
|
||||
features |= ARM_NEON;
|
||||
#endif
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
#elif defined(__ANDROID__) || defined(ANDROID) /* Android */
|
||||
|
||||
static arm_cpu_features_t
|
||||
detect_cpu_features (void)
|
||||
{
|
||||
arm_cpu_features_t features = 0;
|
||||
char buf[1024];
|
||||
char* pos;
|
||||
const char* ver_token = "CPU architecture: ";
|
||||
FILE* f = fopen("/proc/cpuinfo", "r");
|
||||
if (!f) {
|
||||
return features;
|
||||
}
|
||||
|
||||
fread(buf, sizeof(char), sizeof(buf), f);
|
||||
fclose(f);
|
||||
pos = strstr(buf, ver_token);
|
||||
if (pos) {
|
||||
char vchar = *(pos + strlen(ver_token));
|
||||
if (vchar >= '0' && vchar <= '9') {
|
||||
int ver = vchar - '0';
|
||||
if (ver >= 7)
|
||||
features |= ARM_V7;
|
||||
}
|
||||
}
|
||||
if (strstr(buf, "neon") != NULL)
|
||||
features |= ARM_NEON;
|
||||
if (strstr(buf, "vfp") != NULL)
|
||||
features |= ARM_VFP;
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
#elif defined (__linux__) /* linux ELF */
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <elf.h>
|
||||
|
||||
static arm_cpu_features_t
|
||||
detect_cpu_features (void)
|
||||
{
|
||||
arm_cpu_features_t features = 0;
|
||||
Elf32_auxv_t aux;
|
||||
int fd;
|
||||
|
||||
fd = open ("/proc/self/auxv", O_RDONLY);
|
||||
if (fd >= 0)
|
||||
{
|
||||
while (read (fd, &aux, sizeof(Elf32_auxv_t)) == sizeof(Elf32_auxv_t))
|
||||
{
|
||||
if (aux.a_type == AT_HWCAP)
|
||||
{
|
||||
uint32_t hwcap = aux.a_un.a_val;
|
||||
|
||||
/* hardcode these values to avoid depending on specific
|
||||
* versions of the hwcap header, e.g. HWCAP_NEON
|
||||
*/
|
||||
if ((hwcap & 64) != 0)
|
||||
features |= ARM_VFP;
|
||||
if ((hwcap & 512) != 0)
|
||||
features |= ARM_IWMMXT;
|
||||
/* this flag is only present on kernel 2.6.29 */
|
||||
if ((hwcap & 4096) != 0)
|
||||
features |= ARM_NEON;
|
||||
}
|
||||
else if (aux.a_type == AT_PLATFORM)
|
||||
{
|
||||
const char *plat = (const char*) aux.a_un.a_val;
|
||||
|
||||
if (strncmp (plat, "v7l", 3) == 0)
|
||||
features |= (ARM_V7 | ARM_V6);
|
||||
else if (strncmp (plat, "v6l", 3) == 0)
|
||||
features |= ARM_V6;
|
||||
}
|
||||
}
|
||||
close (fd);
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
#else /* Unknown */
|
||||
|
||||
static arm_cpu_features_t
|
||||
detect_cpu_features (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* Linux elf */
|
||||
|
||||
static pixman_bool_t
|
||||
have_feature (arm_cpu_features_t feature)
|
||||
{
|
||||
static pixman_bool_t initialized;
|
||||
static arm_cpu_features_t features;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
features = detect_cpu_features();
|
||||
initialized = TRUE;
|
||||
}
|
||||
|
||||
return (features & feature) == feature;
|
||||
}
|
||||
|
||||
#endif /* USE_ARM_SIMD || USE_ARM_NEON || USE_ARM_IWMMXT */
|
||||
|
||||
pixman_implementation_t *
|
||||
_pixman_arm_get_implementations (pixman_implementation_t *imp)
|
||||
{
|
||||
#ifdef USE_ARM_SIMD
|
||||
if (!_pixman_disabled ("arm-simd") && have_feature (ARM_V6))
|
||||
imp = _pixman_implementation_create_arm_simd (imp);
|
||||
#endif
|
||||
|
||||
#ifdef USE_ARM_IWMMXT
|
||||
if (!_pixman_disabled ("arm-iwmmxt") && have_feature (ARM_IWMMXT))
|
||||
imp = _pixman_implementation_create_mmx (imp);
|
||||
#endif
|
||||
|
||||
#ifdef USE_ARM_NEON
|
||||
if (!_pixman_disabled ("arm-neon") && have_feature (ARM_NEON))
|
||||
imp = _pixman_implementation_create_arm_neon (imp);
|
||||
#endif
|
||||
|
||||
return imp;
|
||||
}
|
||||
1849
gfx/cairo/libpixman/src/pixman-bits-image.c
Normal file
1849
gfx/cairo/libpixman/src/pixman-bits-image.c
Normal file
File diff suppressed because it is too large
Load diff
1018
gfx/cairo/libpixman/src/pixman-combine-float.c
Normal file
1018
gfx/cairo/libpixman/src/pixman-combine-float.c
Normal file
File diff suppressed because it is too large
Load diff
2461
gfx/cairo/libpixman/src/pixman-combine.c.template
Normal file
2461
gfx/cairo/libpixman/src/pixman-combine.c.template
Normal file
File diff suppressed because it is too large
Load diff
226
gfx/cairo/libpixman/src/pixman-combine.h.template
Normal file
226
gfx/cairo/libpixman/src/pixman-combine.h.template
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
|
||||
#define COMPONENT_SIZE
|
||||
#define MASK
|
||||
#define ONE_HALF
|
||||
|
||||
#define A_SHIFT
|
||||
#define R_SHIFT
|
||||
#define G_SHIFT
|
||||
#define A_MASK
|
||||
#define R_MASK
|
||||
#define G_MASK
|
||||
|
||||
#define RB_MASK
|
||||
#define AG_MASK
|
||||
#define RB_ONE_HALF
|
||||
#define RB_MASK_PLUS_ONE
|
||||
|
||||
#define ALPHA_c(x) ((x) >> A_SHIFT)
|
||||
#define RED_c(x) (((x) >> R_SHIFT) & MASK)
|
||||
#define GREEN_c(x) (((x) >> G_SHIFT) & MASK)
|
||||
#define BLUE_c(x) ((x) & MASK)
|
||||
|
||||
/*
|
||||
* Helper macros.
|
||||
*/
|
||||
|
||||
#define MUL_UNc(a, b, t) \
|
||||
((t) = (a) * (comp2_t)(b) + ONE_HALF, ((((t) >> G_SHIFT ) + (t) ) >> G_SHIFT ))
|
||||
|
||||
#define DIV_UNc(a, b) \
|
||||
(((comp2_t) (a) * MASK + ((b) / 2)) / (b))
|
||||
|
||||
#define ADD_UNc(x, y, t) \
|
||||
((t) = (x) + (y), \
|
||||
(comp4_t) (comp1_t) ((t) | (0 - ((t) >> G_SHIFT))))
|
||||
|
||||
#define DIV_ONE_UNc(x) \
|
||||
(((x) + ONE_HALF + (((x) + ONE_HALF) >> G_SHIFT)) >> G_SHIFT)
|
||||
|
||||
/*
|
||||
* The methods below use some tricks to be able to do two color
|
||||
* components at the same time.
|
||||
*/
|
||||
|
||||
/*
|
||||
* x_rb = (x_rb * a) / 255
|
||||
*/
|
||||
#define UNc_rb_MUL_UNc(x, a, t) \
|
||||
do \
|
||||
{ \
|
||||
t = ((x) & RB_MASK) * (a); \
|
||||
t += RB_ONE_HALF; \
|
||||
x = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT; \
|
||||
x &= RB_MASK; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_rb = min (x_rb + y_rb, 255)
|
||||
*/
|
||||
#define UNc_rb_ADD_UNc_rb(x, y, t) \
|
||||
do \
|
||||
{ \
|
||||
t = ((x) + (y)); \
|
||||
t |= RB_MASK_PLUS_ONE - ((t >> G_SHIFT) & RB_MASK); \
|
||||
x = (t & RB_MASK); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_rb = (x_rb * a_rb) / 255
|
||||
*/
|
||||
#define UNc_rb_MUL_UNc_rb(x, a, t) \
|
||||
do \
|
||||
{ \
|
||||
t = (x & MASK) * (a & MASK); \
|
||||
t |= (x & R_MASK) * ((a >> R_SHIFT) & MASK); \
|
||||
t += RB_ONE_HALF; \
|
||||
t = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT; \
|
||||
x = t & RB_MASK; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a) / 255
|
||||
*/
|
||||
#define UNcx4_MUL_UNc(x, a) \
|
||||
do \
|
||||
{ \
|
||||
comp4_t r1__, r2__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
UNc_rb_MUL_UNc (r1__, (a), t__); \
|
||||
\
|
||||
r2__ = (x) >> G_SHIFT; \
|
||||
UNc_rb_MUL_UNc (r2__, (a), t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a) / 255 + y_c
|
||||
*/
|
||||
#define UNcx4_MUL_UNc_ADD_UNcx4(x, a, y) \
|
||||
do \
|
||||
{ \
|
||||
comp4_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (y) & RB_MASK; \
|
||||
UNc_rb_MUL_UNc (r1__, (a), t__); \
|
||||
UNc_rb_ADD_UNc_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = (x) >> G_SHIFT; \
|
||||
r3__ = ((y) >> G_SHIFT) & RB_MASK; \
|
||||
UNc_rb_MUL_UNc (r2__, (a), t__); \
|
||||
UNc_rb_ADD_UNc_rb (r2__, r3__, t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a + y_c * b) / 255
|
||||
*/
|
||||
#define UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc(x, a, y, b) \
|
||||
do \
|
||||
{ \
|
||||
comp4_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (y); \
|
||||
UNc_rb_MUL_UNc (r1__, (a), t__); \
|
||||
UNc_rb_MUL_UNc (r2__, (b), t__); \
|
||||
UNc_rb_ADD_UNc_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = ((x) >> G_SHIFT); \
|
||||
r3__ = ((y) >> G_SHIFT); \
|
||||
UNc_rb_MUL_UNc (r2__, (a), t__); \
|
||||
UNc_rb_MUL_UNc (r3__, (b), t__); \
|
||||
UNc_rb_ADD_UNc_rb (r2__, r3__, t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a_c) / 255
|
||||
*/
|
||||
#define UNcx4_MUL_UNcx4(x, a) \
|
||||
do \
|
||||
{ \
|
||||
comp4_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (a); \
|
||||
UNc_rb_MUL_UNc_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = (x) >> G_SHIFT; \
|
||||
r3__ = (a) >> G_SHIFT; \
|
||||
UNc_rb_MUL_UNc_rb (r2__, r3__, t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a_c) / 255 + y_c
|
||||
*/
|
||||
#define UNcx4_MUL_UNcx4_ADD_UNcx4(x, a, y) \
|
||||
do \
|
||||
{ \
|
||||
comp4_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (a); \
|
||||
UNc_rb_MUL_UNc_rb (r1__, r2__, t__); \
|
||||
r2__ = (y) & RB_MASK; \
|
||||
UNc_rb_ADD_UNc_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = ((x) >> G_SHIFT); \
|
||||
r3__ = ((a) >> G_SHIFT); \
|
||||
UNc_rb_MUL_UNc_rb (r2__, r3__, t__); \
|
||||
r3__ = ((y) >> G_SHIFT) & RB_MASK; \
|
||||
UNc_rb_ADD_UNc_rb (r2__, r3__, t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a_c + y_c * b) / 255
|
||||
*/
|
||||
#define UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc(x, a, y, b) \
|
||||
do \
|
||||
{ \
|
||||
comp4_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (a); \
|
||||
UNc_rb_MUL_UNc_rb (r1__, r2__, t__); \
|
||||
r2__ = (y); \
|
||||
UNc_rb_MUL_UNc (r2__, (b), t__); \
|
||||
UNc_rb_ADD_UNc_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = (x) >> G_SHIFT; \
|
||||
r3__ = (a) >> G_SHIFT; \
|
||||
UNc_rb_MUL_UNc_rb (r2__, r3__, t__); \
|
||||
r3__ = (y) >> G_SHIFT; \
|
||||
UNc_rb_MUL_UNc (r3__, (b), t__); \
|
||||
UNc_rb_ADD_UNc_rb (r2__, r3__, t__); \
|
||||
\
|
||||
x = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
x_c = min(x_c + y_c, 255)
|
||||
*/
|
||||
#define UNcx4_ADD_UNcx4(x, y) \
|
||||
do \
|
||||
{ \
|
||||
comp4_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x) & RB_MASK; \
|
||||
r2__ = (y) & RB_MASK; \
|
||||
UNc_rb_ADD_UNc_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = ((x) >> G_SHIFT) & RB_MASK; \
|
||||
r3__ = ((y) >> G_SHIFT) & RB_MASK; \
|
||||
UNc_rb_ADD_UNc_rb (r2__, r3__, t__); \
|
||||
\
|
||||
x = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
114
gfx/cairo/libpixman/src/pixman-combine16.c
Normal file
114
gfx/cairo/libpixman/src/pixman-combine16.c
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "pixman-private.h"
|
||||
|
||||
#include "pixman-combine32.h"
|
||||
|
||||
static force_inline uint32_t
|
||||
combine_mask (const uint32_t src, const uint32_t mask)
|
||||
{
|
||||
uint32_t s, m;
|
||||
|
||||
m = mask >> A_SHIFT;
|
||||
|
||||
if (!m)
|
||||
return 0;
|
||||
s = src;
|
||||
|
||||
UN8x4_MUL_UN8 (s, m);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static void
|
||||
combine_src_u (pixman_implementation_t *imp,
|
||||
pixman_op_t op,
|
||||
uint32_t * dest,
|
||||
const uint32_t * src,
|
||||
const uint32_t * mask,
|
||||
int width)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!mask)
|
||||
memcpy (dest, src, width * sizeof (uint16_t));
|
||||
else
|
||||
{
|
||||
uint16_t *d = (uint16_t*)dest;
|
||||
uint16_t *src16 = (uint16_t*)src;
|
||||
for (i = 0; i < width; ++i)
|
||||
{
|
||||
if ((*mask & 0xff000000) == 0xff000000) {
|
||||
// it's likely worth special casing
|
||||
// fully opaque because it avoids
|
||||
// the cost of conversion as well the multiplication
|
||||
*(d + i) = *src16;
|
||||
} else {
|
||||
// the mask is still 32bits
|
||||
uint32_t s = combine_mask (convert_0565_to_8888(*src16), *mask);
|
||||
*(d + i) = convert_8888_to_0565(s);
|
||||
}
|
||||
mask++;
|
||||
src16++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
combine_over_u (pixman_implementation_t *imp,
|
||||
pixman_op_t op,
|
||||
uint32_t * dest,
|
||||
const uint32_t * src,
|
||||
const uint32_t * mask,
|
||||
int width)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!mask)
|
||||
memcpy (dest, src, width * sizeof (uint16_t));
|
||||
else
|
||||
{
|
||||
uint16_t *d = (uint16_t*)dest;
|
||||
uint16_t *src16 = (uint16_t*)src;
|
||||
for (i = 0; i < width; ++i)
|
||||
{
|
||||
if ((*mask & 0xff000000) == 0xff000000) {
|
||||
// it's likely worth special casing
|
||||
// fully opaque because it avoids
|
||||
// the cost of conversion as well the multiplication
|
||||
*(d + i) = *src16;
|
||||
} else if ((*mask & 0xff000000) == 0x00000000) {
|
||||
// keep the dest the same
|
||||
} else {
|
||||
// the mask is still 32bits
|
||||
uint32_t s = combine_mask (convert_0565_to_8888(*src16), *mask);
|
||||
uint32_t ia = ALPHA_8 (~s);
|
||||
uint32_t d32 = convert_0565_to_8888(*(d + i));
|
||||
UN8x4_MUL_UN8_ADD_UN8x4 (d32, ia, s);
|
||||
*(d + i) = convert_8888_to_0565(d32);
|
||||
}
|
||||
mask++;
|
||||
src16++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_pixman_setup_combiner_functions_16 (pixman_implementation_t *imp)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < PIXMAN_N_OPERATORS; i++) {
|
||||
imp->combine_16[i] = NULL;
|
||||
}
|
||||
imp->combine_16[PIXMAN_OP_SRC] = combine_src_u;
|
||||
imp->combine_16[PIXMAN_OP_OVER] = combine_over_u;
|
||||
}
|
||||
|
||||
2504
gfx/cairo/libpixman/src/pixman-combine32.c
Normal file
2504
gfx/cairo/libpixman/src/pixman-combine32.c
Normal file
File diff suppressed because it is too large
Load diff
272
gfx/cairo/libpixman/src/pixman-combine32.h
Normal file
272
gfx/cairo/libpixman/src/pixman-combine32.h
Normal file
|
|
@ -0,0 +1,272 @@
|
|||
#define COMPONENT_SIZE 8
|
||||
#define MASK 0xff
|
||||
#define ONE_HALF 0x80
|
||||
|
||||
#define A_SHIFT 8 * 3
|
||||
#define R_SHIFT 8 * 2
|
||||
#define G_SHIFT 8
|
||||
#define A_MASK 0xff000000
|
||||
#define R_MASK 0xff0000
|
||||
#define G_MASK 0xff00
|
||||
|
||||
#define RB_MASK 0xff00ff
|
||||
#define AG_MASK 0xff00ff00
|
||||
#define RB_ONE_HALF 0x800080
|
||||
#define RB_MASK_PLUS_ONE 0x10000100
|
||||
|
||||
#define ALPHA_8(x) ((x) >> A_SHIFT)
|
||||
#define RED_8(x) (((x) >> R_SHIFT) & MASK)
|
||||
#define GREEN_8(x) (((x) >> G_SHIFT) & MASK)
|
||||
#define BLUE_8(x) ((x) & MASK)
|
||||
|
||||
/*
|
||||
* ARMv6 has UQADD8 instruction, which implements unsigned saturated
|
||||
* addition for 8-bit values packed in 32-bit registers. It is very useful
|
||||
* for UN8x4_ADD_UN8x4, UN8_rb_ADD_UN8_rb and ADD_UN8 macros (which would
|
||||
* otherwise need a lot of arithmetic operations to simulate this operation).
|
||||
* Since most of the major ARM linux distros are built for ARMv7, we are
|
||||
* much less dependent on runtime CPU detection and can get practical
|
||||
* benefits from conditional compilation here for a lot of users.
|
||||
*/
|
||||
|
||||
#if defined(USE_GCC_INLINE_ASM) && defined(__arm__) && \
|
||||
!defined(__aarch64__) && (!defined(__thumb__) || defined(__thumb2__))
|
||||
#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \
|
||||
defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || \
|
||||
defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) || \
|
||||
defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_7__) || \
|
||||
defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || \
|
||||
defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
|
||||
|
||||
static force_inline uint32_t
|
||||
un8x4_add_un8x4 (uint32_t x, uint32_t y)
|
||||
{
|
||||
uint32_t t;
|
||||
asm ("uqadd8 %0, %1, %2" : "=r" (t) : "%r" (x), "r" (y));
|
||||
return t;
|
||||
}
|
||||
|
||||
#define UN8x4_ADD_UN8x4(x, y) \
|
||||
((x) = un8x4_add_un8x4 ((x), (y)))
|
||||
|
||||
#define UN8_rb_ADD_UN8_rb(x, y, t) \
|
||||
((t) = un8x4_add_un8x4 ((x), (y)), (x) = (t))
|
||||
|
||||
#define ADD_UN8(x, y, t) \
|
||||
((t) = (x), un8x4_add_un8x4 ((t), (y)))
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Helper macros.
|
||||
*/
|
||||
|
||||
#define MUL_UN8(a, b, t) \
|
||||
((t) = (a) * (uint16_t)(b) + ONE_HALF, ((((t) >> G_SHIFT ) + (t) ) >> G_SHIFT ))
|
||||
|
||||
#define DIV_UN8(a, b) \
|
||||
(((uint16_t) (a) * MASK + ((b) / 2)) / (b))
|
||||
|
||||
#ifndef ADD_UN8
|
||||
#define ADD_UN8(x, y, t) \
|
||||
((t) = (x) + (y), \
|
||||
(uint32_t) (uint8_t) ((t) | (0 - ((t) >> G_SHIFT))))
|
||||
#endif
|
||||
|
||||
#define DIV_ONE_UN8(x) \
|
||||
(((x) + ONE_HALF + (((x) + ONE_HALF) >> G_SHIFT)) >> G_SHIFT)
|
||||
|
||||
/*
|
||||
* The methods below use some tricks to be able to do two color
|
||||
* components at the same time.
|
||||
*/
|
||||
|
||||
/*
|
||||
* x_rb = (x_rb * a) / 255
|
||||
*/
|
||||
#define UN8_rb_MUL_UN8(x, a, t) \
|
||||
do \
|
||||
{ \
|
||||
t = ((x) & RB_MASK) * (a); \
|
||||
t += RB_ONE_HALF; \
|
||||
x = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT; \
|
||||
x &= RB_MASK; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_rb = min (x_rb + y_rb, 255)
|
||||
*/
|
||||
#ifndef UN8_rb_ADD_UN8_rb
|
||||
#define UN8_rb_ADD_UN8_rb(x, y, t) \
|
||||
do \
|
||||
{ \
|
||||
t = ((x) + (y)); \
|
||||
t |= RB_MASK_PLUS_ONE - ((t >> G_SHIFT) & RB_MASK); \
|
||||
x = (t & RB_MASK); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* x_rb = (x_rb * a_rb) / 255
|
||||
*/
|
||||
#define UN8_rb_MUL_UN8_rb(x, a, t) \
|
||||
do \
|
||||
{ \
|
||||
t = (x & MASK) * (a & MASK); \
|
||||
t |= (x & R_MASK) * ((a >> R_SHIFT) & MASK); \
|
||||
t += RB_ONE_HALF; \
|
||||
t = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT; \
|
||||
x = t & RB_MASK; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a) / 255
|
||||
*/
|
||||
#define UN8x4_MUL_UN8(x, a) \
|
||||
do \
|
||||
{ \
|
||||
uint32_t r1__, r2__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
UN8_rb_MUL_UN8 (r1__, (a), t__); \
|
||||
\
|
||||
r2__ = (x) >> G_SHIFT; \
|
||||
UN8_rb_MUL_UN8 (r2__, (a), t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a) / 255 + y_c
|
||||
*/
|
||||
#define UN8x4_MUL_UN8_ADD_UN8x4(x, a, y) \
|
||||
do \
|
||||
{ \
|
||||
uint32_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (y) & RB_MASK; \
|
||||
UN8_rb_MUL_UN8 (r1__, (a), t__); \
|
||||
UN8_rb_ADD_UN8_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = (x) >> G_SHIFT; \
|
||||
r3__ = ((y) >> G_SHIFT) & RB_MASK; \
|
||||
UN8_rb_MUL_UN8 (r2__, (a), t__); \
|
||||
UN8_rb_ADD_UN8_rb (r2__, r3__, t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a + y_c * b) / 255
|
||||
*/
|
||||
#define UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8(x, a, y, b) \
|
||||
do \
|
||||
{ \
|
||||
uint32_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (y); \
|
||||
UN8_rb_MUL_UN8 (r1__, (a), t__); \
|
||||
UN8_rb_MUL_UN8 (r2__, (b), t__); \
|
||||
UN8_rb_ADD_UN8_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = ((x) >> G_SHIFT); \
|
||||
r3__ = ((y) >> G_SHIFT); \
|
||||
UN8_rb_MUL_UN8 (r2__, (a), t__); \
|
||||
UN8_rb_MUL_UN8 (r3__, (b), t__); \
|
||||
UN8_rb_ADD_UN8_rb (r2__, r3__, t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a_c) / 255
|
||||
*/
|
||||
#define UN8x4_MUL_UN8x4(x, a) \
|
||||
do \
|
||||
{ \
|
||||
uint32_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (a); \
|
||||
UN8_rb_MUL_UN8_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = (x) >> G_SHIFT; \
|
||||
r3__ = (a) >> G_SHIFT; \
|
||||
UN8_rb_MUL_UN8_rb (r2__, r3__, t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a_c) / 255 + y_c
|
||||
*/
|
||||
#define UN8x4_MUL_UN8x4_ADD_UN8x4(x, a, y) \
|
||||
do \
|
||||
{ \
|
||||
uint32_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (a); \
|
||||
UN8_rb_MUL_UN8_rb (r1__, r2__, t__); \
|
||||
r2__ = (y) & RB_MASK; \
|
||||
UN8_rb_ADD_UN8_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = ((x) >> G_SHIFT); \
|
||||
r3__ = ((a) >> G_SHIFT); \
|
||||
UN8_rb_MUL_UN8_rb (r2__, r3__, t__); \
|
||||
r3__ = ((y) >> G_SHIFT) & RB_MASK; \
|
||||
UN8_rb_ADD_UN8_rb (r2__, r3__, t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a_c + y_c * b) / 255
|
||||
*/
|
||||
#define UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8(x, a, y, b) \
|
||||
do \
|
||||
{ \
|
||||
uint32_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (a); \
|
||||
UN8_rb_MUL_UN8_rb (r1__, r2__, t__); \
|
||||
r2__ = (y); \
|
||||
UN8_rb_MUL_UN8 (r2__, (b), t__); \
|
||||
UN8_rb_ADD_UN8_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = (x) >> G_SHIFT; \
|
||||
r3__ = (a) >> G_SHIFT; \
|
||||
UN8_rb_MUL_UN8_rb (r2__, r3__, t__); \
|
||||
r3__ = (y) >> G_SHIFT; \
|
||||
UN8_rb_MUL_UN8 (r3__, (b), t__); \
|
||||
UN8_rb_ADD_UN8_rb (r2__, r3__, t__); \
|
||||
\
|
||||
x = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
x_c = min(x_c + y_c, 255)
|
||||
*/
|
||||
#ifndef UN8x4_ADD_UN8x4
|
||||
#define UN8x4_ADD_UN8x4(x, y) \
|
||||
do \
|
||||
{ \
|
||||
uint32_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x) & RB_MASK; \
|
||||
r2__ = (y) & RB_MASK; \
|
||||
UN8_rb_ADD_UN8_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = ((x) >> G_SHIFT) & RB_MASK; \
|
||||
r3__ = ((y) >> G_SHIFT) & RB_MASK; \
|
||||
UN8_rb_ADD_UN8_rb (r2__, r3__, t__); \
|
||||
\
|
||||
x = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
#endif
|
||||
2465
gfx/cairo/libpixman/src/pixman-combine64.c
Normal file
2465
gfx/cairo/libpixman/src/pixman-combine64.c
Normal file
File diff suppressed because it is too large
Load diff
230
gfx/cairo/libpixman/src/pixman-combine64.h
Normal file
230
gfx/cairo/libpixman/src/pixman-combine64.h
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
/* WARNING: This file is generated by combine.pl from combine.inc.
|
||||
Please edit one of those files rather than this one. */
|
||||
|
||||
#line 1 "pixman-combine.c.template"
|
||||
|
||||
#define COMPONENT_SIZE 16
|
||||
#define MASK 0xffffULL
|
||||
#define ONE_HALF 0x8000ULL
|
||||
|
||||
#define A_SHIFT 16 * 3
|
||||
#define R_SHIFT 16 * 2
|
||||
#define G_SHIFT 16
|
||||
#define A_MASK 0xffff000000000000ULL
|
||||
#define R_MASK 0xffff00000000ULL
|
||||
#define G_MASK 0xffff0000ULL
|
||||
|
||||
#define RB_MASK 0xffff0000ffffULL
|
||||
#define AG_MASK 0xffff0000ffff0000ULL
|
||||
#define RB_ONE_HALF 0x800000008000ULL
|
||||
#define RB_MASK_PLUS_ONE 0x10000000010000ULL
|
||||
|
||||
#define ALPHA_16(x) ((x) >> A_SHIFT)
|
||||
#define RED_16(x) (((x) >> R_SHIFT) & MASK)
|
||||
#define GREEN_16(x) (((x) >> G_SHIFT) & MASK)
|
||||
#define BLUE_16(x) ((x) & MASK)
|
||||
|
||||
/*
|
||||
* Helper macros.
|
||||
*/
|
||||
|
||||
#define MUL_UN16(a, b, t) \
|
||||
((t) = (a) * (uint32_t)(b) + ONE_HALF, ((((t) >> G_SHIFT ) + (t) ) >> G_SHIFT ))
|
||||
|
||||
#define DIV_UN16(a, b) \
|
||||
(((uint32_t) (a) * MASK + ((b) / 2)) / (b))
|
||||
|
||||
#define ADD_UN16(x, y, t) \
|
||||
((t) = (x) + (y), \
|
||||
(uint64_t) (uint16_t) ((t) | (0 - ((t) >> G_SHIFT))))
|
||||
|
||||
#define DIV_ONE_UN16(x) \
|
||||
(((x) + ONE_HALF + (((x) + ONE_HALF) >> G_SHIFT)) >> G_SHIFT)
|
||||
|
||||
/*
|
||||
* The methods below use some tricks to be able to do two color
|
||||
* components at the same time.
|
||||
*/
|
||||
|
||||
/*
|
||||
* x_rb = (x_rb * a) / 255
|
||||
*/
|
||||
#define UN16_rb_MUL_UN16(x, a, t) \
|
||||
do \
|
||||
{ \
|
||||
t = ((x) & RB_MASK) * (a); \
|
||||
t += RB_ONE_HALF; \
|
||||
x = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT; \
|
||||
x &= RB_MASK; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_rb = min (x_rb + y_rb, 255)
|
||||
*/
|
||||
#define UN16_rb_ADD_UN16_rb(x, y, t) \
|
||||
do \
|
||||
{ \
|
||||
t = ((x) + (y)); \
|
||||
t |= RB_MASK_PLUS_ONE - ((t >> G_SHIFT) & RB_MASK); \
|
||||
x = (t & RB_MASK); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_rb = (x_rb * a_rb) / 255
|
||||
*/
|
||||
#define UN16_rb_MUL_UN16_rb(x, a, t) \
|
||||
do \
|
||||
{ \
|
||||
t = (x & MASK) * (a & MASK); \
|
||||
t |= (x & R_MASK) * ((a >> R_SHIFT) & MASK); \
|
||||
t += RB_ONE_HALF; \
|
||||
t = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT; \
|
||||
x = t & RB_MASK; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a) / 255
|
||||
*/
|
||||
#define UN16x4_MUL_UN16(x, a) \
|
||||
do \
|
||||
{ \
|
||||
uint64_t r1__, r2__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
UN16_rb_MUL_UN16 (r1__, (a), t__); \
|
||||
\
|
||||
r2__ = (x) >> G_SHIFT; \
|
||||
UN16_rb_MUL_UN16 (r2__, (a), t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a) / 255 + y_c
|
||||
*/
|
||||
#define UN16x4_MUL_UN16_ADD_UN16x4(x, a, y) \
|
||||
do \
|
||||
{ \
|
||||
uint64_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (y) & RB_MASK; \
|
||||
UN16_rb_MUL_UN16 (r1__, (a), t__); \
|
||||
UN16_rb_ADD_UN16_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = (x) >> G_SHIFT; \
|
||||
r3__ = ((y) >> G_SHIFT) & RB_MASK; \
|
||||
UN16_rb_MUL_UN16 (r2__, (a), t__); \
|
||||
UN16_rb_ADD_UN16_rb (r2__, r3__, t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a + y_c * b) / 255
|
||||
*/
|
||||
#define UN16x4_MUL_UN16_ADD_UN16x4_MUL_UN16(x, a, y, b) \
|
||||
do \
|
||||
{ \
|
||||
uint64_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (y); \
|
||||
UN16_rb_MUL_UN16 (r1__, (a), t__); \
|
||||
UN16_rb_MUL_UN16 (r2__, (b), t__); \
|
||||
UN16_rb_ADD_UN16_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = ((x) >> G_SHIFT); \
|
||||
r3__ = ((y) >> G_SHIFT); \
|
||||
UN16_rb_MUL_UN16 (r2__, (a), t__); \
|
||||
UN16_rb_MUL_UN16 (r3__, (b), t__); \
|
||||
UN16_rb_ADD_UN16_rb (r2__, r3__, t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a_c) / 255
|
||||
*/
|
||||
#define UN16x4_MUL_UN16x4(x, a) \
|
||||
do \
|
||||
{ \
|
||||
uint64_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (a); \
|
||||
UN16_rb_MUL_UN16_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = (x) >> G_SHIFT; \
|
||||
r3__ = (a) >> G_SHIFT; \
|
||||
UN16_rb_MUL_UN16_rb (r2__, r3__, t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a_c) / 255 + y_c
|
||||
*/
|
||||
#define UN16x4_MUL_UN16x4_ADD_UN16x4(x, a, y) \
|
||||
do \
|
||||
{ \
|
||||
uint64_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (a); \
|
||||
UN16_rb_MUL_UN16_rb (r1__, r2__, t__); \
|
||||
r2__ = (y) & RB_MASK; \
|
||||
UN16_rb_ADD_UN16_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = ((x) >> G_SHIFT); \
|
||||
r3__ = ((a) >> G_SHIFT); \
|
||||
UN16_rb_MUL_UN16_rb (r2__, r3__, t__); \
|
||||
r3__ = ((y) >> G_SHIFT) & RB_MASK; \
|
||||
UN16_rb_ADD_UN16_rb (r2__, r3__, t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a_c + y_c * b) / 255
|
||||
*/
|
||||
#define UN16x4_MUL_UN16x4_ADD_UN16x4_MUL_UN16(x, a, y, b) \
|
||||
do \
|
||||
{ \
|
||||
uint64_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (a); \
|
||||
UN16_rb_MUL_UN16_rb (r1__, r2__, t__); \
|
||||
r2__ = (y); \
|
||||
UN16_rb_MUL_UN16 (r2__, (b), t__); \
|
||||
UN16_rb_ADD_UN16_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = (x) >> G_SHIFT; \
|
||||
r3__ = (a) >> G_SHIFT; \
|
||||
UN16_rb_MUL_UN16_rb (r2__, r3__, t__); \
|
||||
r3__ = (y) >> G_SHIFT; \
|
||||
UN16_rb_MUL_UN16 (r3__, (b), t__); \
|
||||
UN16_rb_ADD_UN16_rb (r2__, r3__, t__); \
|
||||
\
|
||||
x = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
x_c = min(x_c + y_c, 255)
|
||||
*/
|
||||
#define UN16x4_ADD_UN16x4(x, y) \
|
||||
do \
|
||||
{ \
|
||||
uint64_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x) & RB_MASK; \
|
||||
r2__ = (y) & RB_MASK; \
|
||||
UN16_rb_ADD_UN16_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = ((x) >> G_SHIFT) & RB_MASK; \
|
||||
r3__ = ((y) >> G_SHIFT) & RB_MASK; \
|
||||
UN16_rb_ADD_UN16_rb (r2__, r3__, t__); \
|
||||
\
|
||||
x = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
247
gfx/cairo/libpixman/src/pixman-compiler.h
Normal file
247
gfx/cairo/libpixman/src/pixman-compiler.h
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
/* Pixman uses some non-standard compiler features. This file ensures
|
||||
* they exist
|
||||
*
|
||||
* The features are:
|
||||
*
|
||||
* FUNC must be defined to expand to the current function
|
||||
* PIXMAN_EXPORT should be defined to whatever is required to
|
||||
* export functions from a shared library
|
||||
* limits limits for various types must be defined
|
||||
* inline must be defined
|
||||
* force_inline must be defined
|
||||
*/
|
||||
#if defined (__GNUC__)
|
||||
# define FUNC ((const char*) (__PRETTY_FUNCTION__))
|
||||
#elif defined (__sun) || (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)
|
||||
# define FUNC ((const char*) (__func__))
|
||||
#else
|
||||
# define FUNC ((const char*) ("???"))
|
||||
#endif
|
||||
|
||||
#if defined (__GNUC__)
|
||||
# define MAYBE_UNUSED __attribute__((unused))
|
||||
#else
|
||||
# define MAYBE_UNUSED
|
||||
#endif
|
||||
|
||||
#ifndef INT16_MIN
|
||||
# define INT16_MIN (-32767-1)
|
||||
#endif
|
||||
|
||||
#ifndef INT16_MAX
|
||||
# define INT16_MAX (32767)
|
||||
#endif
|
||||
|
||||
#ifndef INT32_MIN
|
||||
# define INT32_MIN (-2147483647-1)
|
||||
#endif
|
||||
|
||||
#ifndef INT32_MAX
|
||||
# define INT32_MAX (2147483647)
|
||||
#endif
|
||||
|
||||
#ifndef UINT32_MIN
|
||||
# define UINT32_MIN (0)
|
||||
#endif
|
||||
|
||||
#ifndef UINT32_MAX
|
||||
# define UINT32_MAX (4294967295U)
|
||||
#endif
|
||||
|
||||
#ifndef INT64_MIN
|
||||
# define INT64_MIN (-9223372036854775807-1)
|
||||
#endif
|
||||
|
||||
#ifndef INT64_MAX
|
||||
# define INT64_MAX (9223372036854775807)
|
||||
#endif
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
# define SIZE_MAX ((size_t)-1)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef M_PI
|
||||
# define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
/* 'inline' is available only in C++ in MSVC */
|
||||
# define inline __inline
|
||||
# define force_inline __forceinline
|
||||
# define noinline __declspec(noinline)
|
||||
#elif defined __GNUC__ || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
|
||||
# define inline __inline__
|
||||
# define force_inline __inline__ __attribute__ ((__always_inline__))
|
||||
# define noinline __attribute__((noinline))
|
||||
#else
|
||||
# ifndef force_inline
|
||||
# define force_inline inline
|
||||
# endif
|
||||
# ifndef noinline
|
||||
# define noinline
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* In libxul builds we don't ever want to export pixman symbols */
|
||||
#if 1
|
||||
#include "prcpucfg.h"
|
||||
|
||||
#ifdef HAVE_VISIBILITY_HIDDEN_ATTRIBUTE
|
||||
#define CVISIBILITY_HIDDEN __attribute__((visibility("hidden")))
|
||||
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
|
||||
#define CVISIBILITY_HIDDEN __hidden
|
||||
#else
|
||||
#define CVISIBILITY_HIDDEN
|
||||
#endif
|
||||
|
||||
/* In libxul builds we don't ever want to export cairo symbols */
|
||||
#define PIXMAN_EXPORT extern CVISIBILITY_HIDDEN
|
||||
|
||||
#else
|
||||
|
||||
/* GCC visibility */
|
||||
#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(_WIN32)
|
||||
# define PIXMAN_EXPORT __attribute__ ((visibility("default")))
|
||||
/* Sun Studio 8 visibility */
|
||||
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
|
||||
# define PIXMAN_EXPORT __global
|
||||
#else
|
||||
# define PIXMAN_EXPORT
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* member offsets */
|
||||
#define CONTAINER_OF(type, member, data) \
|
||||
((type *)(((uint8_t *)data) - offsetof (type, member)))
|
||||
|
||||
/* TLS */
|
||||
#if defined(PIXMAN_NO_TLS)
|
||||
|
||||
# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \
|
||||
static type name
|
||||
# define PIXMAN_GET_THREAD_LOCAL(name) \
|
||||
(&name)
|
||||
|
||||
#elif defined(TLS)
|
||||
|
||||
# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \
|
||||
static TLS type name
|
||||
# define PIXMAN_GET_THREAD_LOCAL(name) \
|
||||
(&name)
|
||||
|
||||
#elif defined(__MINGW32__) || defined(PIXMAN_USE_XP_DLL_TLS_WORKAROUND)
|
||||
|
||||
# define _NO_W32_PSEUDO_MODIFIERS
|
||||
# include <windows.h>
|
||||
#undef IN
|
||||
#undef OUT
|
||||
|
||||
# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \
|
||||
static volatile int tls_ ## name ## _initialized = 0; \
|
||||
static void *tls_ ## name ## _mutex = NULL; \
|
||||
static unsigned tls_ ## name ## _index; \
|
||||
\
|
||||
static type * \
|
||||
tls_ ## name ## _alloc (void) \
|
||||
{ \
|
||||
type *value = calloc (1, sizeof (type)); \
|
||||
if (value) \
|
||||
TlsSetValue (tls_ ## name ## _index, value); \
|
||||
return value; \
|
||||
} \
|
||||
\
|
||||
static force_inline type * \
|
||||
tls_ ## name ## _get (void) \
|
||||
{ \
|
||||
type *value; \
|
||||
if (!tls_ ## name ## _initialized) \
|
||||
{ \
|
||||
if (!tls_ ## name ## _mutex) \
|
||||
{ \
|
||||
void *mutex = CreateMutexA (NULL, 0, NULL); \
|
||||
if (InterlockedCompareExchangePointer ( \
|
||||
&tls_ ## name ## _mutex, mutex, NULL) != NULL) \
|
||||
{ \
|
||||
CloseHandle (mutex); \
|
||||
} \
|
||||
} \
|
||||
WaitForSingleObject (tls_ ## name ## _mutex, 0xFFFFFFFF); \
|
||||
if (!tls_ ## name ## _initialized) \
|
||||
{ \
|
||||
tls_ ## name ## _index = TlsAlloc (); \
|
||||
tls_ ## name ## _initialized = 1; \
|
||||
} \
|
||||
ReleaseMutex (tls_ ## name ## _mutex); \
|
||||
} \
|
||||
if (tls_ ## name ## _index == 0xFFFFFFFF) \
|
||||
return NULL; \
|
||||
value = TlsGetValue (tls_ ## name ## _index); \
|
||||
if (!value) \
|
||||
value = tls_ ## name ## _alloc (); \
|
||||
return value; \
|
||||
}
|
||||
|
||||
# define PIXMAN_GET_THREAD_LOCAL(name) \
|
||||
tls_ ## name ## _get ()
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
|
||||
# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \
|
||||
static __declspec(thread) type name
|
||||
# define PIXMAN_GET_THREAD_LOCAL(name) \
|
||||
(&name)
|
||||
|
||||
#elif defined(HAVE_PTHREAD_SETSPECIFIC)
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \
|
||||
static pthread_once_t tls_ ## name ## _once_control = PTHREAD_ONCE_INIT; \
|
||||
static pthread_key_t tls_ ## name ## _key; \
|
||||
\
|
||||
static void \
|
||||
tls_ ## name ## _destroy_value (void *value) \
|
||||
{ \
|
||||
free (value); \
|
||||
} \
|
||||
\
|
||||
static void \
|
||||
tls_ ## name ## _make_key (void) \
|
||||
{ \
|
||||
pthread_key_create (&tls_ ## name ## _key, \
|
||||
tls_ ## name ## _destroy_value); \
|
||||
} \
|
||||
\
|
||||
static type * \
|
||||
tls_ ## name ## _alloc (void) \
|
||||
{ \
|
||||
type *value = calloc (1, sizeof (type)); \
|
||||
if (value) \
|
||||
pthread_setspecific (tls_ ## name ## _key, value); \
|
||||
return value; \
|
||||
} \
|
||||
\
|
||||
static force_inline type * \
|
||||
tls_ ## name ## _get (void) \
|
||||
{ \
|
||||
type *value = NULL; \
|
||||
if (pthread_once (&tls_ ## name ## _once_control, \
|
||||
tls_ ## name ## _make_key) == 0) \
|
||||
{ \
|
||||
value = pthread_getspecific (tls_ ## name ## _key); \
|
||||
if (!value) \
|
||||
value = tls_ ## name ## _alloc (); \
|
||||
} \
|
||||
return value; \
|
||||
}
|
||||
|
||||
# define PIXMAN_GET_THREAD_LOCAL(name) \
|
||||
tls_ ## name ## _get ()
|
||||
|
||||
#else
|
||||
|
||||
# error "Unknown thread local support for this system. Pixman will not work with multiple threads. Define PIXMAN_NO_TLS to acknowledge and accept this limitation and compile pixman without thread-safety support."
|
||||
|
||||
#endif
|
||||
212
gfx/cairo/libpixman/src/pixman-conical-gradient.c
Normal file
212
gfx/cairo/libpixman/src/pixman-conical-gradient.c
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
* Copyright © 2000 SuSE, Inc.
|
||||
* Copyright © 2007 Red Hat, Inc.
|
||||
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
|
||||
* 2005 Lars Knoll & Zack Rusin, Trolltech
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "pixman-private.h"
|
||||
|
||||
static force_inline double
|
||||
coordinates_to_parameter (double x, double y, double angle)
|
||||
{
|
||||
double t;
|
||||
|
||||
t = atan2 (y, x) + angle;
|
||||
|
||||
while (t < 0)
|
||||
t += 2 * M_PI;
|
||||
|
||||
while (t >= 2 * M_PI)
|
||||
t -= 2 * M_PI;
|
||||
|
||||
return 1 - t * (1 / (2 * M_PI)); /* Scale t to [0, 1] and
|
||||
* make rotation CCW
|
||||
*/
|
||||
}
|
||||
|
||||
static uint32_t *
|
||||
conical_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
pixman_image_t *image = iter->image;
|
||||
int x = iter->x;
|
||||
int y = iter->y;
|
||||
int width = iter->width;
|
||||
uint32_t *buffer = iter->buffer;
|
||||
|
||||
gradient_t *gradient = (gradient_t *)image;
|
||||
conical_gradient_t *conical = (conical_gradient_t *)image;
|
||||
uint32_t *end = buffer + width;
|
||||
pixman_gradient_walker_t walker;
|
||||
pixman_bool_t affine = TRUE;
|
||||
double cx = 1.;
|
||||
double cy = 0.;
|
||||
double cz = 0.;
|
||||
double rx = x + 0.5;
|
||||
double ry = y + 0.5;
|
||||
double rz = 1.;
|
||||
|
||||
_pixman_gradient_walker_init (&walker, gradient, image->common.repeat);
|
||||
|
||||
if (image->common.transform)
|
||||
{
|
||||
pixman_vector_t v;
|
||||
|
||||
/* reference point is the center of the pixel */
|
||||
v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2;
|
||||
v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2;
|
||||
v.vector[2] = pixman_fixed_1;
|
||||
|
||||
if (!pixman_transform_point_3d (image->common.transform, &v))
|
||||
return iter->buffer;
|
||||
|
||||
cx = image->common.transform->matrix[0][0] / 65536.;
|
||||
cy = image->common.transform->matrix[1][0] / 65536.;
|
||||
cz = image->common.transform->matrix[2][0] / 65536.;
|
||||
|
||||
rx = v.vector[0] / 65536.;
|
||||
ry = v.vector[1] / 65536.;
|
||||
rz = v.vector[2] / 65536.;
|
||||
|
||||
affine =
|
||||
image->common.transform->matrix[2][0] == 0 &&
|
||||
v.vector[2] == pixman_fixed_1;
|
||||
}
|
||||
|
||||
if (affine)
|
||||
{
|
||||
rx -= conical->center.x / 65536.;
|
||||
ry -= conical->center.y / 65536.;
|
||||
|
||||
while (buffer < end)
|
||||
{
|
||||
if (!mask || *mask++)
|
||||
{
|
||||
double t = coordinates_to_parameter (rx, ry, conical->angle);
|
||||
|
||||
*buffer = _pixman_gradient_walker_pixel (
|
||||
&walker, (pixman_fixed_48_16_t)pixman_double_to_fixed (t));
|
||||
}
|
||||
|
||||
++buffer;
|
||||
|
||||
rx += cx;
|
||||
ry += cy;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (buffer < end)
|
||||
{
|
||||
double x, y;
|
||||
|
||||
if (!mask || *mask++)
|
||||
{
|
||||
double t;
|
||||
|
||||
if (rz != 0)
|
||||
{
|
||||
x = rx / rz;
|
||||
y = ry / rz;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = y = 0.;
|
||||
}
|
||||
|
||||
x -= conical->center.x / 65536.;
|
||||
y -= conical->center.y / 65536.;
|
||||
|
||||
t = coordinates_to_parameter (x, y, conical->angle);
|
||||
|
||||
*buffer = _pixman_gradient_walker_pixel (
|
||||
&walker, (pixman_fixed_48_16_t)pixman_double_to_fixed (t));
|
||||
}
|
||||
|
||||
++buffer;
|
||||
|
||||
rx += cx;
|
||||
ry += cy;
|
||||
rz += cz;
|
||||
}
|
||||
}
|
||||
|
||||
iter->y++;
|
||||
return iter->buffer;
|
||||
}
|
||||
|
||||
static uint32_t *
|
||||
conical_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
uint32_t *buffer = conical_get_scanline_narrow (iter, NULL);
|
||||
|
||||
pixman_expand_to_float (
|
||||
(argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void
|
||||
_pixman_conical_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter)
|
||||
{
|
||||
if (iter->iter_flags & ITER_NARROW)
|
||||
iter->get_scanline = conical_get_scanline_narrow;
|
||||
else
|
||||
iter->get_scanline = conical_get_scanline_wide;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT pixman_image_t *
|
||||
pixman_image_create_conical_gradient (const pixman_point_fixed_t * center,
|
||||
pixman_fixed_t angle,
|
||||
const pixman_gradient_stop_t *stops,
|
||||
int n_stops)
|
||||
{
|
||||
pixman_image_t *image = _pixman_image_allocate ();
|
||||
conical_gradient_t *conical;
|
||||
|
||||
if (!image)
|
||||
return NULL;
|
||||
|
||||
conical = &image->conical;
|
||||
|
||||
if (!_pixman_init_gradient (&conical->common, stops, n_stops))
|
||||
{
|
||||
free (image);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
angle = MOD (angle, pixman_int_to_fixed (360));
|
||||
|
||||
image->type = CONICAL;
|
||||
|
||||
conical->center = *center;
|
||||
conical->angle = (pixman_fixed_to_double (angle) / 180.0) * M_PI;
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
799
gfx/cairo/libpixman/src/pixman-cpu.c
Normal file
799
gfx/cairo/libpixman/src/pixman-cpu.c
Normal file
|
|
@ -0,0 +1,799 @@
|
|||
/*
|
||||
* Copyright © 2000 SuSE, Inc.
|
||||
* Copyright © 2007 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of SuSE not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. SuSE makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
|
||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(USE_ARM_SIMD) && defined(_MSC_VER)
|
||||
/* Needed for EXCEPTION_ILLEGAL_INSTRUCTION */
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include "TargetConditionals.h"
|
||||
#endif
|
||||
|
||||
#include "pixman-private.h"
|
||||
|
||||
#ifdef USE_VMX
|
||||
|
||||
/* The CPU detection code needs to be in a file not compiled with
|
||||
* "-maltivec -mabi=altivec", as gcc would try to save vector register
|
||||
* across function calls causing SIGILL on cpus without Altivec/vmx.
|
||||
*/
|
||||
static pixman_bool_t initialized = FALSE;
|
||||
static volatile pixman_bool_t have_vmx = TRUE;
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
static pixman_bool_t
|
||||
pixman_have_vmx (void)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
size_t length = sizeof(have_vmx);
|
||||
int error =
|
||||
sysctlbyname ("hw.optional.altivec", &have_vmx, &length, NULL, 0);
|
||||
|
||||
if (error)
|
||||
have_vmx = FALSE;
|
||||
|
||||
initialized = TRUE;
|
||||
}
|
||||
return have_vmx;
|
||||
}
|
||||
|
||||
#elif defined (__OpenBSD__)
|
||||
#include <sys/param.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <machine/cpu.h>
|
||||
|
||||
static pixman_bool_t
|
||||
pixman_have_vmx (void)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
int mib[2] = { CTL_MACHDEP, CPU_ALTIVEC };
|
||||
size_t length = sizeof(have_vmx);
|
||||
int error =
|
||||
sysctl (mib, 2, &have_vmx, &length, NULL, 0);
|
||||
|
||||
if (error != 0)
|
||||
have_vmx = FALSE;
|
||||
|
||||
initialized = TRUE;
|
||||
}
|
||||
return have_vmx;
|
||||
}
|
||||
|
||||
#elif defined (__linux__)
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <linux/auxvec.h>
|
||||
#include <asm/cputable.h>
|
||||
|
||||
static pixman_bool_t
|
||||
pixman_have_vmx (void)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
char fname[64];
|
||||
unsigned long buf[64];
|
||||
ssize_t count = 0;
|
||||
pid_t pid;
|
||||
int fd, i;
|
||||
|
||||
pid = getpid ();
|
||||
snprintf (fname, sizeof(fname) - 1, "/proc/%d/auxv", pid);
|
||||
|
||||
fd = open (fname, O_RDONLY);
|
||||
if (fd >= 0)
|
||||
{
|
||||
for (i = 0; i <= (count / sizeof(unsigned long)); i += 2)
|
||||
{
|
||||
/* Read more if buf is empty... */
|
||||
if (i == (count / sizeof(unsigned long)))
|
||||
{
|
||||
count = read (fd, buf, sizeof(buf));
|
||||
if (count <= 0)
|
||||
break;
|
||||
i = 0;
|
||||
}
|
||||
|
||||
if (buf[i] == AT_HWCAP)
|
||||
{
|
||||
have_vmx = !!(buf[i + 1] & PPC_FEATURE_HAS_ALTIVEC);
|
||||
initialized = TRUE;
|
||||
break;
|
||||
}
|
||||
else if (buf[i] == AT_NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
close (fd);
|
||||
}
|
||||
}
|
||||
if (!initialized)
|
||||
{
|
||||
/* Something went wrong. Assume 'no' rather than playing
|
||||
fragile tricks with catching SIGILL. */
|
||||
have_vmx = FALSE;
|
||||
initialized = TRUE;
|
||||
}
|
||||
|
||||
return have_vmx;
|
||||
}
|
||||
|
||||
#else /* !__APPLE__ && !__OpenBSD__ && !__linux__ */
|
||||
#include <signal.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
static jmp_buf jump_env;
|
||||
|
||||
static void
|
||||
vmx_test (int sig,
|
||||
siginfo_t *si,
|
||||
void * unused)
|
||||
{
|
||||
longjmp (jump_env, 1);
|
||||
}
|
||||
|
||||
static pixman_bool_t
|
||||
pixman_have_vmx (void)
|
||||
{
|
||||
struct sigaction sa, osa;
|
||||
int jmp_result;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
sigemptyset (&sa.sa_mask);
|
||||
sa.sa_sigaction = vmx_test;
|
||||
sigaction (SIGILL, &sa, &osa);
|
||||
jmp_result = setjmp (jump_env);
|
||||
if (jmp_result == 0)
|
||||
{
|
||||
asm volatile ( "vor 0, 0, 0" );
|
||||
}
|
||||
sigaction (SIGILL, &osa, NULL);
|
||||
have_vmx = (jmp_result == 0);
|
||||
initialized = TRUE;
|
||||
}
|
||||
return have_vmx;
|
||||
}
|
||||
|
||||
#endif /* __APPLE__ */
|
||||
#endif /* USE_VMX */
|
||||
|
||||
#if defined(USE_ARM_SIMD) || defined(USE_ARM_NEON) || defined(USE_ARM_IWMMXT)
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
#if defined(USE_ARM_SIMD)
|
||||
extern int pixman_msvc_try_arm_simd_op ();
|
||||
|
||||
pixman_bool_t
|
||||
pixman_have_arm_simd (void)
|
||||
{
|
||||
static pixman_bool_t initialized = FALSE;
|
||||
static pixman_bool_t have_arm_simd = FALSE;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
__try {
|
||||
pixman_msvc_try_arm_simd_op ();
|
||||
have_arm_simd = TRUE;
|
||||
} __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION) {
|
||||
have_arm_simd = FALSE;
|
||||
}
|
||||
initialized = TRUE;
|
||||
}
|
||||
|
||||
return have_arm_simd;
|
||||
}
|
||||
|
||||
#endif /* USE_ARM_SIMD */
|
||||
|
||||
#if defined(USE_ARM_NEON)
|
||||
extern int pixman_msvc_try_arm_neon_op ();
|
||||
|
||||
pixman_bool_t
|
||||
pixman_have_arm_neon (void)
|
||||
{
|
||||
static pixman_bool_t initialized = FALSE;
|
||||
static pixman_bool_t have_arm_neon = FALSE;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
__try
|
||||
{
|
||||
pixman_msvc_try_arm_neon_op ();
|
||||
have_arm_neon = TRUE;
|
||||
}
|
||||
__except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION)
|
||||
{
|
||||
have_arm_neon = FALSE;
|
||||
}
|
||||
initialized = TRUE;
|
||||
}
|
||||
|
||||
return have_arm_neon;
|
||||
}
|
||||
|
||||
#endif /* USE_ARM_NEON */
|
||||
|
||||
#elif (defined (__APPLE__) && defined(TARGET_OS_IPHONE)) /* iOS (iPhone/iPad/iPod touch) */
|
||||
|
||||
/* Detection of ARM NEON on iOS is fairly simple because iOS binaries
|
||||
* contain separate executable images for each processor architecture.
|
||||
* So all we have to do is detect the armv7 architecture build. The
|
||||
* operating system automatically runs the armv7 binary for armv7 devices
|
||||
* and the armv6 binary for armv6 devices.
|
||||
*/
|
||||
|
||||
pixman_bool_t
|
||||
pixman_have_arm_simd (void)
|
||||
{
|
||||
#if defined(USE_ARM_SIMD)
|
||||
return TRUE;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
pixman_bool_t
|
||||
pixman_have_arm_neon (void)
|
||||
{
|
||||
#if defined(USE_ARM_NEON) && defined(__ARM_NEON__)
|
||||
/* This is an armv7 cpu build */
|
||||
return TRUE;
|
||||
#else
|
||||
/* This is an armv6 cpu build */
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
pixman_bool_t
|
||||
pixman_have_arm_iwmmxt (void)
|
||||
{
|
||||
#if defined(USE_ARM_IWMMXT)
|
||||
return FALSE;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
#elif defined (__linux__) || defined(__ANDROID__) || defined(ANDROID) /* linux ELF or ANDROID */
|
||||
|
||||
static pixman_bool_t arm_has_v7 = FALSE;
|
||||
static pixman_bool_t arm_has_v6 = FALSE;
|
||||
static pixman_bool_t arm_has_vfp = FALSE;
|
||||
static pixman_bool_t arm_has_neon = FALSE;
|
||||
static pixman_bool_t arm_has_iwmmxt = FALSE;
|
||||
static pixman_bool_t arm_tests_initialized = FALSE;
|
||||
|
||||
#if defined(__ANDROID__) || defined(ANDROID) /* Android device support */
|
||||
|
||||
static void
|
||||
pixman_arm_read_auxv_or_cpu_features ()
|
||||
{
|
||||
char buf[1024];
|
||||
char* pos;
|
||||
const char* ver_token = "CPU architecture: ";
|
||||
FILE* f = fopen("/proc/cpuinfo", "r");
|
||||
if (!f) {
|
||||
arm_tests_initialized = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
fread(buf, sizeof(char), sizeof(buf), f);
|
||||
fclose(f);
|
||||
pos = strstr(buf, ver_token);
|
||||
if (pos) {
|
||||
char vchar = *(pos + strlen(ver_token));
|
||||
if (vchar >= '0' && vchar <= '9') {
|
||||
int ver = vchar - '0';
|
||||
arm_has_v7 = ver >= 7;
|
||||
arm_has_v6 = ver >= 6;
|
||||
}
|
||||
}
|
||||
arm_has_neon = strstr(buf, "neon") != NULL;
|
||||
arm_has_vfp = strstr(buf, "vfp") != NULL;
|
||||
arm_has_iwmmxt = strstr(buf, "iwmmxt") != NULL;
|
||||
arm_tests_initialized = TRUE;
|
||||
}
|
||||
|
||||
#elif defined (__linux__) /* linux ELF */
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <elf.h>
|
||||
|
||||
static void
|
||||
pixman_arm_read_auxv_or_cpu_features ()
|
||||
{
|
||||
int fd;
|
||||
Elf32_auxv_t aux;
|
||||
|
||||
fd = open ("/proc/self/auxv", O_RDONLY);
|
||||
if (fd >= 0)
|
||||
{
|
||||
while (read (fd, &aux, sizeof(Elf32_auxv_t)) == sizeof(Elf32_auxv_t))
|
||||
{
|
||||
if (aux.a_type == AT_HWCAP)
|
||||
{
|
||||
uint32_t hwcap = aux.a_un.a_val;
|
||||
/* hardcode these values to avoid depending on specific
|
||||
* versions of the hwcap header, e.g. HWCAP_NEON
|
||||
*/
|
||||
arm_has_vfp = (hwcap & 64) != 0;
|
||||
arm_has_iwmmxt = (hwcap & 512) != 0;
|
||||
/* this flag is only present on kernel 2.6.29 */
|
||||
arm_has_neon = (hwcap & 4096) != 0;
|
||||
}
|
||||
else if (aux.a_type == AT_PLATFORM)
|
||||
{
|
||||
const char *plat = (const char*) aux.a_un.a_val;
|
||||
if (strncmp (plat, "v7l", 3) == 0)
|
||||
{
|
||||
arm_has_v7 = TRUE;
|
||||
arm_has_v6 = TRUE;
|
||||
}
|
||||
else if (strncmp (plat, "v6l", 3) == 0)
|
||||
{
|
||||
arm_has_v6 = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
close (fd);
|
||||
}
|
||||
|
||||
arm_tests_initialized = TRUE;
|
||||
}
|
||||
|
||||
#endif /* Linux elf */
|
||||
|
||||
#if defined(USE_ARM_SIMD)
|
||||
pixman_bool_t
|
||||
pixman_have_arm_simd (void)
|
||||
{
|
||||
if (!arm_tests_initialized)
|
||||
pixman_arm_read_auxv_or_cpu_features ();
|
||||
|
||||
return arm_has_v6;
|
||||
}
|
||||
|
||||
#endif /* USE_ARM_SIMD */
|
||||
|
||||
#if defined(USE_ARM_NEON)
|
||||
pixman_bool_t
|
||||
pixman_have_arm_neon (void)
|
||||
{
|
||||
if (!arm_tests_initialized)
|
||||
pixman_arm_read_auxv_or_cpu_features ();
|
||||
|
||||
return arm_has_neon;
|
||||
}
|
||||
|
||||
#endif /* USE_ARM_NEON */
|
||||
|
||||
#if defined(USE_ARM_IWMMXT)
|
||||
pixman_bool_t
|
||||
pixman_have_arm_iwmmxt (void)
|
||||
{
|
||||
if (!arm_tests_initialized)
|
||||
pixman_arm_read_auxv_or_cpu_features ();
|
||||
|
||||
return arm_has_iwmmxt;
|
||||
}
|
||||
|
||||
#endif /* USE_ARM_IWMMXT */
|
||||
|
||||
#else /* !_MSC_VER && !Linux elf && !Android */
|
||||
|
||||
#define pixman_have_arm_simd() FALSE
|
||||
#define pixman_have_arm_neon() FALSE
|
||||
#define pixman_have_arm_iwmmxt() FALSE
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* USE_ARM_SIMD || USE_ARM_NEON || USE_ARM_IWMMXT */
|
||||
|
||||
#if defined(USE_MIPS_DSPR2)
|
||||
|
||||
#if defined (__linux__) /* linux ELF */
|
||||
|
||||
pixman_bool_t
|
||||
pixman_have_mips_dspr2 (void)
|
||||
{
|
||||
const char *search_string = "MIPS 74K";
|
||||
const char *file_name = "/proc/cpuinfo";
|
||||
/* Simple detection of MIPS DSP ASE (revision 2) at runtime for Linux.
|
||||
* It is based on /proc/cpuinfo, which reveals hardware configuration
|
||||
* to user-space applications. According to MIPS (early 2010), no similar
|
||||
* facility is universally available on the MIPS architectures, so it's up
|
||||
* to individual OSes to provide such.
|
||||
*
|
||||
* Only currently available MIPS core that supports DSPr2 is 74K.
|
||||
*/
|
||||
|
||||
char cpuinfo_line[256];
|
||||
|
||||
FILE *f = NULL;
|
||||
|
||||
if ((f = fopen (file_name, "r")) == NULL)
|
||||
return FALSE;
|
||||
|
||||
while (fgets (cpuinfo_line, sizeof (cpuinfo_line), f) != NULL)
|
||||
{
|
||||
if (strstr (cpuinfo_line, search_string) != NULL)
|
||||
{
|
||||
fclose (f);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
fclose (f);
|
||||
|
||||
/* Did not find string in the proc file. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#else /* linux ELF */
|
||||
|
||||
#define pixman_have_mips_dspr2() FALSE
|
||||
|
||||
#endif /* linux ELF */
|
||||
|
||||
#endif /* USE_MIPS_DSPR2 */
|
||||
|
||||
#if defined(USE_X86_MMX) || defined(USE_SSE2)
|
||||
/* The CPU detection code needs to be in a file not compiled with
|
||||
* "-mmmx -msse", as gcc would generate CMOV instructions otherwise
|
||||
* that would lead to SIGILL instructions on old CPUs that don't have
|
||||
* it.
|
||||
*/
|
||||
#if !defined(__amd64__) && !defined(__x86_64__) && !defined(_M_AMD64)
|
||||
|
||||
#ifdef HAVE_GETISAX
|
||||
#include <sys/auxv.h>
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NO_FEATURES = 0,
|
||||
MMX = 0x1,
|
||||
MMX_EXTENSIONS = 0x2,
|
||||
SSE = 0x6,
|
||||
SSE2 = 0x8,
|
||||
CMOV = 0x10
|
||||
} cpu_features_t;
|
||||
|
||||
|
||||
static unsigned int
|
||||
detect_cpu_features (void)
|
||||
{
|
||||
unsigned int features = 0;
|
||||
unsigned int result = 0;
|
||||
|
||||
#ifdef HAVE_GETISAX
|
||||
if (getisax (&result, 1))
|
||||
{
|
||||
if (result & AV_386_CMOV)
|
||||
features |= CMOV;
|
||||
if (result & AV_386_MMX)
|
||||
features |= MMX;
|
||||
if (result & AV_386_AMD_MMX)
|
||||
features |= MMX_EXTENSIONS;
|
||||
if (result & AV_386_SSE)
|
||||
features |= SSE;
|
||||
if (result & AV_386_SSE2)
|
||||
features |= SSE2;
|
||||
}
|
||||
#else
|
||||
char vendor[13];
|
||||
#ifdef _MSC_VER
|
||||
int vendor0 = 0, vendor1, vendor2;
|
||||
#endif
|
||||
vendor[0] = 0;
|
||||
vendor[12] = 0;
|
||||
|
||||
#ifdef __GNUC__
|
||||
/* see p. 118 of amd64 instruction set manual Vol3 */
|
||||
/* We need to be careful about the handling of %ebx and
|
||||
* %esp here. We can't declare either one as clobbered
|
||||
* since they are special registers (%ebx is the "PIC
|
||||
* register" holding an offset to global data, %esp the
|
||||
* stack pointer), so we need to make sure they have their
|
||||
* original values when we access the output operands.
|
||||
*/
|
||||
__asm__ (
|
||||
"pushf\n"
|
||||
"pop %%eax\n"
|
||||
"mov %%eax, %%ecx\n"
|
||||
"xor $0x00200000, %%eax\n"
|
||||
"push %%eax\n"
|
||||
"popf\n"
|
||||
"pushf\n"
|
||||
"pop %%eax\n"
|
||||
"mov $0x0, %%edx\n"
|
||||
"xor %%ecx, %%eax\n"
|
||||
"jz 1f\n"
|
||||
|
||||
"mov $0x00000000, %%eax\n"
|
||||
"push %%ebx\n"
|
||||
"cpuid\n"
|
||||
"mov %%ebx, %%eax\n"
|
||||
"pop %%ebx\n"
|
||||
"mov %%eax, %1\n"
|
||||
"mov %%edx, %2\n"
|
||||
"mov %%ecx, %3\n"
|
||||
"mov $0x00000001, %%eax\n"
|
||||
"push %%ebx\n"
|
||||
"cpuid\n"
|
||||
"pop %%ebx\n"
|
||||
"1:\n"
|
||||
"mov %%edx, %0\n"
|
||||
: "=r" (result),
|
||||
"=m" (vendor[0]),
|
||||
"=m" (vendor[4]),
|
||||
"=m" (vendor[8])
|
||||
:
|
||||
: "%eax", "%ecx", "%edx"
|
||||
);
|
||||
|
||||
#elif defined (_MSC_VER)
|
||||
|
||||
_asm {
|
||||
pushfd
|
||||
pop eax
|
||||
mov ecx, eax
|
||||
xor eax, 00200000h
|
||||
push eax
|
||||
popfd
|
||||
pushfd
|
||||
pop eax
|
||||
mov edx, 0
|
||||
xor eax, ecx
|
||||
jz nocpuid
|
||||
|
||||
mov eax, 0
|
||||
push ebx
|
||||
cpuid
|
||||
mov eax, ebx
|
||||
pop ebx
|
||||
mov vendor0, eax
|
||||
mov vendor1, edx
|
||||
mov vendor2, ecx
|
||||
mov eax, 1
|
||||
push ebx
|
||||
cpuid
|
||||
pop ebx
|
||||
nocpuid:
|
||||
mov result, edx
|
||||
}
|
||||
memmove (vendor + 0, &vendor0, 4);
|
||||
memmove (vendor + 4, &vendor1, 4);
|
||||
memmove (vendor + 8, &vendor2, 4);
|
||||
|
||||
#else
|
||||
# error unsupported compiler
|
||||
#endif
|
||||
|
||||
features = 0;
|
||||
if (result)
|
||||
{
|
||||
/* result now contains the standard feature bits */
|
||||
if (result & (1 << 15))
|
||||
features |= CMOV;
|
||||
if (result & (1 << 23))
|
||||
features |= MMX;
|
||||
if (result & (1 << 25))
|
||||
features |= SSE;
|
||||
if (result & (1 << 26))
|
||||
features |= SSE2;
|
||||
if ((features & MMX) && !(features & SSE) &&
|
||||
(strcmp (vendor, "AuthenticAMD") == 0 ||
|
||||
strcmp (vendor, "Geode by NSC") == 0))
|
||||
{
|
||||
/* check for AMD MMX extensions */
|
||||
#ifdef __GNUC__
|
||||
__asm__ (
|
||||
" push %%ebx\n"
|
||||
" mov $0x80000000, %%eax\n"
|
||||
" cpuid\n"
|
||||
" xor %%edx, %%edx\n"
|
||||
" cmp $0x1, %%eax\n"
|
||||
" jge 2f\n"
|
||||
" mov $0x80000001, %%eax\n"
|
||||
" cpuid\n"
|
||||
"2:\n"
|
||||
" pop %%ebx\n"
|
||||
" mov %%edx, %0\n"
|
||||
: "=r" (result)
|
||||
:
|
||||
: "%eax", "%ecx", "%edx"
|
||||
);
|
||||
#elif defined _MSC_VER
|
||||
_asm {
|
||||
push ebx
|
||||
mov eax, 80000000h
|
||||
cpuid
|
||||
xor edx, edx
|
||||
cmp eax, 1
|
||||
jge notamd
|
||||
mov eax, 80000001h
|
||||
cpuid
|
||||
notamd:
|
||||
pop ebx
|
||||
mov result, edx
|
||||
}
|
||||
#endif
|
||||
if (result & (1 << 22))
|
||||
features |= MMX_EXTENSIONS;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_GETISAX */
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
#ifdef USE_X86_MMX
|
||||
static pixman_bool_t
|
||||
pixman_have_mmx (void)
|
||||
{
|
||||
static pixman_bool_t initialized = FALSE;
|
||||
static pixman_bool_t mmx_present;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
unsigned int features = detect_cpu_features ();
|
||||
mmx_present = (features & (MMX | MMX_EXTENSIONS)) == (MMX | MMX_EXTENSIONS);
|
||||
initialized = TRUE;
|
||||
}
|
||||
|
||||
return mmx_present;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_SSE2
|
||||
static pixman_bool_t
|
||||
pixman_have_sse2 (void)
|
||||
{
|
||||
static pixman_bool_t initialized = FALSE;
|
||||
static pixman_bool_t sse2_present;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
unsigned int features = detect_cpu_features ();
|
||||
sse2_present = (features & (MMX | MMX_EXTENSIONS | SSE | SSE2)) == (MMX | MMX_EXTENSIONS | SSE | SSE2);
|
||||
initialized = TRUE;
|
||||
}
|
||||
|
||||
return sse2_present;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#else /* __amd64__ */
|
||||
#ifdef USE_X86_MMX
|
||||
#define pixman_have_mmx() TRUE
|
||||
#endif
|
||||
#ifdef USE_SSE2
|
||||
#define pixman_have_sse2() TRUE
|
||||
#endif
|
||||
#endif /* __amd64__ */
|
||||
#endif
|
||||
|
||||
static pixman_bool_t
|
||||
disabled (const char *name)
|
||||
{
|
||||
const char *env;
|
||||
|
||||
if ((env = getenv ("PIXMAN_DISABLE")))
|
||||
{
|
||||
do
|
||||
{
|
||||
const char *end;
|
||||
int len;
|
||||
|
||||
if ((end = strchr (env, ' ')))
|
||||
len = end - env;
|
||||
else
|
||||
len = strlen (env);
|
||||
|
||||
if (strlen (name) == len && strncmp (name, env, len) == 0)
|
||||
{
|
||||
printf ("pixman: Disabled %s implementation\n", name);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
env += len;
|
||||
}
|
||||
while (*env++);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pixman_implementation_t *
|
||||
_pixman_choose_implementation (void)
|
||||
{
|
||||
pixman_implementation_t *imp;
|
||||
|
||||
imp = _pixman_implementation_create_general();
|
||||
|
||||
if (!disabled ("fast"))
|
||||
imp = _pixman_implementation_create_fast_path (imp);
|
||||
|
||||
#ifdef USE_X86_MMX
|
||||
if (!disabled ("mmx") && pixman_have_mmx ())
|
||||
imp = _pixman_implementation_create_mmx (imp);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SSE2
|
||||
if (!disabled ("sse2") && pixman_have_sse2 ())
|
||||
imp = _pixman_implementation_create_sse2 (imp);
|
||||
#endif
|
||||
|
||||
#ifdef USE_ARM_SIMD
|
||||
if (!disabled ("arm-simd") && pixman_have_arm_simd ())
|
||||
imp = _pixman_implementation_create_arm_simd (imp);
|
||||
#endif
|
||||
|
||||
#ifdef USE_ARM_IWMMXT
|
||||
if (!disabled ("arm-iwmmxt") && pixman_have_arm_iwmmxt ())
|
||||
imp = _pixman_implementation_create_mmx (imp);
|
||||
#endif
|
||||
|
||||
#ifdef USE_ARM_NEON
|
||||
if (!disabled ("arm-neon") && pixman_have_arm_neon ())
|
||||
imp = _pixman_implementation_create_arm_neon (imp);
|
||||
#endif
|
||||
|
||||
#ifdef USE_MIPS_DSPR2
|
||||
if (!disabled ("mips-dspr2") && pixman_have_mips_dspr2 ())
|
||||
imp = _pixman_implementation_create_mips_dspr2 (imp);
|
||||
#endif
|
||||
|
||||
#ifdef USE_VMX
|
||||
if (!disabled ("vmx") && pixman_have_vmx ())
|
||||
imp = _pixman_implementation_create_vmx (imp);
|
||||
#endif
|
||||
|
||||
imp = _pixman_implementation_create_noop (imp);
|
||||
|
||||
return imp;
|
||||
}
|
||||
|
||||
51
gfx/cairo/libpixman/src/pixman-dither.h
Normal file
51
gfx/cairo/libpixman/src/pixman-dither.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#define R16_BITS 5
|
||||
#define G16_BITS 6
|
||||
#define B16_BITS 5
|
||||
|
||||
#define R16_SHIFT (B16_BITS + G16_BITS)
|
||||
#define G16_SHIFT (B16_BITS)
|
||||
#define B16_SHIFT 0
|
||||
|
||||
#define MASK 0xff
|
||||
#define ONE_HALF 0x80
|
||||
|
||||
#define A_SHIFT 8 * 3
|
||||
#define R_SHIFT 8 * 2
|
||||
#define G_SHIFT 8
|
||||
#define A_MASK 0xff000000
|
||||
#define R_MASK 0xff0000
|
||||
#define G_MASK 0xff00
|
||||
|
||||
#define RB_MASK 0xff00ff
|
||||
#define AG_MASK 0xff00ff00
|
||||
#define RB_ONE_HALF 0x800080
|
||||
#define RB_MASK_PLUS_ONE 0x10000100
|
||||
|
||||
#define ALPHA_8(x) ((x) >> A_SHIFT)
|
||||
#define RED_8(x) (((x) >> R_SHIFT) & MASK)
|
||||
#define GREEN_8(x) (((x) >> G_SHIFT) & MASK)
|
||||
#define BLUE_8(x) ((x) & MASK)
|
||||
|
||||
// This uses the same dithering technique that Skia does.
|
||||
// It is essentially preturbing the lower bit based on the
|
||||
// high bit
|
||||
static inline uint16_t dither_32_to_16(uint32_t c)
|
||||
{
|
||||
uint8_t b = BLUE_8(c);
|
||||
uint8_t g = GREEN_8(c);
|
||||
uint8_t r = RED_8(c);
|
||||
r = ((r << 1) - ((r >> (8 - R16_BITS) << (8 - R16_BITS)) | (r >> R16_BITS))) >> (8 - R16_BITS);
|
||||
g = ((g << 1) - ((g >> (8 - G16_BITS) << (8 - G16_BITS)) | (g >> G16_BITS))) >> (8 - G16_BITS);
|
||||
b = ((b << 1) - ((b >> (8 - B16_BITS) << (8 - B16_BITS)) | (b >> B16_BITS))) >> (8 - B16_BITS);
|
||||
return ((r << R16_SHIFT) | (g << G16_SHIFT) | (b << B16_SHIFT));
|
||||
}
|
||||
|
||||
static inline uint16_t dither_8888_to_0565(uint32_t color, pixman_bool_t toggle)
|
||||
{
|
||||
// alternate between a preturbed truncation and a regular truncation
|
||||
if (toggle) {
|
||||
return dither_32_to_16(color);
|
||||
} else {
|
||||
return convert_8888_to_0565(color);
|
||||
}
|
||||
}
|
||||
4
gfx/cairo/libpixman/src/pixman-edge-accessors.c
Normal file
4
gfx/cairo/libpixman/src/pixman-edge-accessors.c
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
#define PIXMAN_FB_ACCESSORS
|
||||
|
||||
#include "pixman-edge.c"
|
||||
183
gfx/cairo/libpixman/src/pixman-edge-imp.h
Normal file
183
gfx/cairo/libpixman/src/pixman-edge-imp.h
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* Copyright © 2004 Keith Packard
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef rasterize_span
|
||||
#endif
|
||||
|
||||
static void
|
||||
RASTERIZE_EDGES (pixman_image_t *image,
|
||||
pixman_edge_t *l,
|
||||
pixman_edge_t *r,
|
||||
pixman_fixed_t t,
|
||||
pixman_fixed_t b)
|
||||
{
|
||||
pixman_fixed_t y = t;
|
||||
uint32_t *line;
|
||||
uint32_t *buf = (image)->bits.bits;
|
||||
int stride = (image)->bits.rowstride;
|
||||
int width = (image)->bits.width;
|
||||
|
||||
line = buf + pixman_fixed_to_int (y) * stride;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
pixman_fixed_t lx;
|
||||
pixman_fixed_t rx;
|
||||
int lxi;
|
||||
int rxi;
|
||||
|
||||
lx = l->x;
|
||||
rx = r->x;
|
||||
#if N_BITS == 1
|
||||
/* For the non-antialiased case, round the coordinates up, in effect
|
||||
* sampling just slightly to the left of the pixel. This is so that
|
||||
* when the sample point lies exactly on the line, we round towards
|
||||
* north-west.
|
||||
*
|
||||
* (The AA case does a similar adjustment in RENDER_SAMPLES_X)
|
||||
*/
|
||||
/* we cast to unsigned to get defined behaviour for overflow */
|
||||
lx = (unsigned)lx + X_FRAC_FIRST(1) - pixman_fixed_e;
|
||||
rx = (unsigned)rx + X_FRAC_FIRST(1) - pixman_fixed_e;
|
||||
#endif
|
||||
/* clip X */
|
||||
if (lx < 0)
|
||||
lx = 0;
|
||||
if (pixman_fixed_to_int (rx) >= width)
|
||||
#if N_BITS == 1
|
||||
rx = pixman_int_to_fixed (width);
|
||||
#else
|
||||
/* Use the last pixel of the scanline, covered 100%.
|
||||
* We can't use the first pixel following the scanline,
|
||||
* because accessing it could result in a buffer overrun.
|
||||
*/
|
||||
rx = pixman_int_to_fixed (width) - 1;
|
||||
#endif
|
||||
|
||||
/* Skip empty (or backwards) sections */
|
||||
if (rx > lx)
|
||||
{
|
||||
|
||||
/* Find pixel bounds for span */
|
||||
lxi = pixman_fixed_to_int (lx);
|
||||
rxi = pixman_fixed_to_int (rx);
|
||||
|
||||
#if N_BITS == 1
|
||||
{
|
||||
|
||||
#define LEFT_MASK(x) \
|
||||
(((x) & 0x1f) ? \
|
||||
SCREEN_SHIFT_RIGHT (0xffffffff, (x) & 0x1f) : 0)
|
||||
#define RIGHT_MASK(x) \
|
||||
(((32 - (x)) & 0x1f) ? \
|
||||
SCREEN_SHIFT_LEFT (0xffffffff, (32 - (x)) & 0x1f) : 0)
|
||||
|
||||
#define MASK_BITS(x,w,l,n,r) { \
|
||||
n = (w); \
|
||||
r = RIGHT_MASK ((x) + n); \
|
||||
l = LEFT_MASK (x); \
|
||||
if (l) { \
|
||||
n -= 32 - ((x) & 0x1f); \
|
||||
if (n < 0) { \
|
||||
n = 0; \
|
||||
l &= r; \
|
||||
r = 0; \
|
||||
} \
|
||||
} \
|
||||
n >>= 5; \
|
||||
}
|
||||
|
||||
uint32_t *a = line;
|
||||
uint32_t startmask;
|
||||
uint32_t endmask;
|
||||
int nmiddle;
|
||||
int width = rxi - lxi;
|
||||
int x = lxi;
|
||||
|
||||
a += x >> 5;
|
||||
x &= 0x1f;
|
||||
|
||||
MASK_BITS (x, width, startmask, nmiddle, endmask);
|
||||
|
||||
if (startmask) {
|
||||
WRITE(image, a, READ(image, a) | startmask);
|
||||
a++;
|
||||
}
|
||||
while (nmiddle--)
|
||||
WRITE(image, a++, 0xffffffff);
|
||||
if (endmask)
|
||||
WRITE(image, a, READ(image, a) | endmask);
|
||||
}
|
||||
#else
|
||||
{
|
||||
DEFINE_ALPHA(line,lxi);
|
||||
int lxs;
|
||||
int rxs;
|
||||
|
||||
/* Sample coverage for edge pixels */
|
||||
lxs = RENDER_SAMPLES_X (lx, N_BITS);
|
||||
rxs = RENDER_SAMPLES_X (rx, N_BITS);
|
||||
|
||||
/* Add coverage across row */
|
||||
if (lxi == rxi)
|
||||
{
|
||||
ADD_ALPHA (rxs - lxs);
|
||||
}
|
||||
else
|
||||
{
|
||||
int xi;
|
||||
|
||||
ADD_ALPHA (N_X_FRAC(N_BITS) - lxs);
|
||||
STEP_ALPHA;
|
||||
for (xi = lxi + 1; xi < rxi; xi++)
|
||||
{
|
||||
ADD_ALPHA (N_X_FRAC(N_BITS));
|
||||
STEP_ALPHA;
|
||||
}
|
||||
ADD_ALPHA (rxs);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (y == b)
|
||||
break;
|
||||
|
||||
#if N_BITS > 1
|
||||
if (pixman_fixed_frac (y) != Y_FRAC_LAST(N_BITS))
|
||||
{
|
||||
RENDER_EDGE_STEP_SMALL (l);
|
||||
RENDER_EDGE_STEP_SMALL (r);
|
||||
y += STEP_Y_SMALL(N_BITS);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
RENDER_EDGE_STEP_BIG (l);
|
||||
RENDER_EDGE_STEP_BIG (r);
|
||||
y += STEP_Y_BIG(N_BITS);
|
||||
line += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef rasterize_span
|
||||
385
gfx/cairo/libpixman/src/pixman-edge.c
Normal file
385
gfx/cairo/libpixman/src/pixman-edge.c
Normal file
|
|
@ -0,0 +1,385 @@
|
|||
/*
|
||||
* Copyright © 2004 Keith Packard
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "pixman-private.h"
|
||||
#include "pixman-accessor.h"
|
||||
|
||||
/*
|
||||
* Step across a small sample grid gap
|
||||
*/
|
||||
#define RENDER_EDGE_STEP_SMALL(edge) \
|
||||
{ \
|
||||
edge->x += edge->stepx_small; \
|
||||
edge->e += edge->dx_small; \
|
||||
if (edge->e > 0) \
|
||||
{ \
|
||||
edge->e -= edge->dy; \
|
||||
edge->x += edge->signdx; \
|
||||
} \
|
||||
}
|
||||
|
||||
/*
|
||||
* Step across a large sample grid gap
|
||||
*/
|
||||
#define RENDER_EDGE_STEP_BIG(edge) \
|
||||
{ \
|
||||
edge->x += edge->stepx_big; \
|
||||
edge->e += edge->dx_big; \
|
||||
if (edge->e > 0) \
|
||||
{ \
|
||||
edge->e -= edge->dy; \
|
||||
edge->x += edge->signdx; \
|
||||
} \
|
||||
}
|
||||
|
||||
#ifdef PIXMAN_FB_ACCESSORS
|
||||
#define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_accessors
|
||||
#else
|
||||
#define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_no_accessors
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 4 bit alpha
|
||||
*/
|
||||
|
||||
#define N_BITS 4
|
||||
#define RASTERIZE_EDGES rasterize_edges_4
|
||||
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
#define SHIFT_4(o) ((o) << 2)
|
||||
#else
|
||||
#define SHIFT_4(o) ((1 - (o)) << 2)
|
||||
#endif
|
||||
|
||||
#define GET_4(x, o) (((x) >> SHIFT_4 (o)) & 0xf)
|
||||
#define PUT_4(x, o, v) \
|
||||
(((x) & ~(0xf << SHIFT_4 (o))) | (((v) & 0xf) << SHIFT_4 (o)))
|
||||
|
||||
#define DEFINE_ALPHA(line, x) \
|
||||
uint8_t *__ap = (uint8_t *) line + ((x) >> 1); \
|
||||
int __ao = (x) & 1
|
||||
|
||||
#define STEP_ALPHA ((__ap += __ao), (__ao ^= 1))
|
||||
|
||||
#define ADD_ALPHA(a) \
|
||||
{ \
|
||||
uint8_t __o = READ (image, __ap); \
|
||||
uint8_t __a = (a) + GET_4 (__o, __ao); \
|
||||
WRITE (image, __ap, PUT_4 (__o, __ao, __a | (0 - ((__a) >> 4)))); \
|
||||
}
|
||||
|
||||
#include "pixman-edge-imp.h"
|
||||
|
||||
#undef ADD_ALPHA
|
||||
#undef STEP_ALPHA
|
||||
#undef DEFINE_ALPHA
|
||||
#undef RASTERIZE_EDGES
|
||||
#undef N_BITS
|
||||
|
||||
|
||||
/*
|
||||
* 1 bit alpha
|
||||
*/
|
||||
|
||||
#define N_BITS 1
|
||||
#define RASTERIZE_EDGES rasterize_edges_1
|
||||
|
||||
#include "pixman-edge-imp.h"
|
||||
|
||||
#undef RASTERIZE_EDGES
|
||||
#undef N_BITS
|
||||
|
||||
/*
|
||||
* 8 bit alpha
|
||||
*/
|
||||
|
||||
static force_inline uint8_t
|
||||
clip255 (int x)
|
||||
{
|
||||
if (x > 255)
|
||||
return 255;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
#define ADD_SATURATE_8(buf, val, length) \
|
||||
do \
|
||||
{ \
|
||||
int i__ = (length); \
|
||||
uint8_t *buf__ = (buf); \
|
||||
int val__ = (val); \
|
||||
\
|
||||
while (i__--) \
|
||||
{ \
|
||||
WRITE (image, (buf__), clip255 (READ (image, (buf__)) + (val__))); \
|
||||
(buf__)++; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* We want to detect the case where we add the same value to a long
|
||||
* span of pixels. The triangles on the end are filled in while we
|
||||
* count how many sub-pixel scanlines contribute to the middle section.
|
||||
*
|
||||
* +--------------------------+
|
||||
* fill_height =| \ /
|
||||
* +------------------+
|
||||
* |================|
|
||||
* fill_start fill_end
|
||||
*/
|
||||
static void
|
||||
rasterize_edges_8 (pixman_image_t *image,
|
||||
pixman_edge_t * l,
|
||||
pixman_edge_t * r,
|
||||
pixman_fixed_t t,
|
||||
pixman_fixed_t b)
|
||||
{
|
||||
pixman_fixed_t y = t;
|
||||
uint32_t *line;
|
||||
int fill_start = -1, fill_end = -1;
|
||||
int fill_size = 0;
|
||||
uint32_t *buf = (image)->bits.bits;
|
||||
int stride = (image)->bits.rowstride;
|
||||
int width = (image)->bits.width;
|
||||
|
||||
line = buf + pixman_fixed_to_int (y) * stride;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
uint8_t *ap = (uint8_t *) line;
|
||||
pixman_fixed_t lx, rx;
|
||||
int lxi, rxi;
|
||||
|
||||
/* clip X */
|
||||
lx = l->x;
|
||||
if (lx < 0)
|
||||
lx = 0;
|
||||
|
||||
rx = r->x;
|
||||
|
||||
if (pixman_fixed_to_int (rx) >= width)
|
||||
{
|
||||
/* Use the last pixel of the scanline, covered 100%.
|
||||
* We can't use the first pixel following the scanline,
|
||||
* because accessing it could result in a buffer overrun.
|
||||
*/
|
||||
rx = pixman_int_to_fixed (width) - 1;
|
||||
}
|
||||
|
||||
/* Skip empty (or backwards) sections */
|
||||
if (rx > lx)
|
||||
{
|
||||
int lxs, rxs;
|
||||
|
||||
/* Find pixel bounds for span. */
|
||||
lxi = pixman_fixed_to_int (lx);
|
||||
rxi = pixman_fixed_to_int (rx);
|
||||
|
||||
/* Sample coverage for edge pixels */
|
||||
lxs = RENDER_SAMPLES_X (lx, 8);
|
||||
rxs = RENDER_SAMPLES_X (rx, 8);
|
||||
|
||||
/* Add coverage across row */
|
||||
if (lxi == rxi)
|
||||
{
|
||||
WRITE (image, ap + lxi,
|
||||
clip255 (READ (image, ap + lxi) + rxs - lxs));
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE (image, ap + lxi,
|
||||
clip255 (READ (image, ap + lxi) + N_X_FRAC (8) - lxs));
|
||||
|
||||
/* Move forward so that lxi/rxi is the pixel span */
|
||||
lxi++;
|
||||
|
||||
/* Don't bother trying to optimize the fill unless
|
||||
* the span is longer than 4 pixels. */
|
||||
if (rxi - lxi > 4)
|
||||
{
|
||||
if (fill_start < 0)
|
||||
{
|
||||
fill_start = lxi;
|
||||
fill_end = rxi;
|
||||
fill_size++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lxi >= fill_end || rxi < fill_start)
|
||||
{
|
||||
/* We're beyond what we saved, just fill it */
|
||||
ADD_SATURATE_8 (ap + fill_start,
|
||||
fill_size * N_X_FRAC (8),
|
||||
fill_end - fill_start);
|
||||
fill_start = lxi;
|
||||
fill_end = rxi;
|
||||
fill_size = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update fill_start */
|
||||
if (lxi > fill_start)
|
||||
{
|
||||
ADD_SATURATE_8 (ap + fill_start,
|
||||
fill_size * N_X_FRAC (8),
|
||||
lxi - fill_start);
|
||||
fill_start = lxi;
|
||||
}
|
||||
else if (lxi < fill_start)
|
||||
{
|
||||
ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8),
|
||||
fill_start - lxi);
|
||||
}
|
||||
|
||||
/* Update fill_end */
|
||||
if (rxi < fill_end)
|
||||
{
|
||||
ADD_SATURATE_8 (ap + rxi,
|
||||
fill_size * N_X_FRAC (8),
|
||||
fill_end - rxi);
|
||||
fill_end = rxi;
|
||||
}
|
||||
else if (fill_end < rxi)
|
||||
{
|
||||
ADD_SATURATE_8 (ap + fill_end,
|
||||
N_X_FRAC (8),
|
||||
rxi - fill_end);
|
||||
}
|
||||
fill_size++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8), rxi - lxi);
|
||||
}
|
||||
|
||||
WRITE (image, ap + rxi, clip255 (READ (image, ap + rxi) + rxs));
|
||||
}
|
||||
}
|
||||
|
||||
if (y == b)
|
||||
{
|
||||
/* We're done, make sure we clean up any remaining fill. */
|
||||
if (fill_start != fill_end)
|
||||
{
|
||||
if (fill_size == N_Y_FRAC (8))
|
||||
{
|
||||
MEMSET_WRAPPED (image, ap + fill_start,
|
||||
0xff, fill_end - fill_start);
|
||||
}
|
||||
else
|
||||
{
|
||||
ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8),
|
||||
fill_end - fill_start);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (pixman_fixed_frac (y) != Y_FRAC_LAST (8))
|
||||
{
|
||||
RENDER_EDGE_STEP_SMALL (l);
|
||||
RENDER_EDGE_STEP_SMALL (r);
|
||||
y += STEP_Y_SMALL (8);
|
||||
}
|
||||
else
|
||||
{
|
||||
RENDER_EDGE_STEP_BIG (l);
|
||||
RENDER_EDGE_STEP_BIG (r);
|
||||
y += STEP_Y_BIG (8);
|
||||
if (fill_start != fill_end)
|
||||
{
|
||||
if (fill_size == N_Y_FRAC (8))
|
||||
{
|
||||
MEMSET_WRAPPED (image, ap + fill_start,
|
||||
0xff, fill_end - fill_start);
|
||||
}
|
||||
else
|
||||
{
|
||||
ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8),
|
||||
fill_end - fill_start);
|
||||
}
|
||||
|
||||
fill_start = fill_end = -1;
|
||||
fill_size = 0;
|
||||
}
|
||||
|
||||
line += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef PIXMAN_FB_ACCESSORS
|
||||
static
|
||||
#endif
|
||||
void
|
||||
PIXMAN_RASTERIZE_EDGES (pixman_image_t *image,
|
||||
pixman_edge_t * l,
|
||||
pixman_edge_t * r,
|
||||
pixman_fixed_t t,
|
||||
pixman_fixed_t b)
|
||||
{
|
||||
switch (PIXMAN_FORMAT_BPP (image->bits.format))
|
||||
{
|
||||
case 1:
|
||||
rasterize_edges_1 (image, l, r, t, b);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
rasterize_edges_4 (image, l, r, t, b);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
rasterize_edges_8 (image, l, r, t, b);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef PIXMAN_FB_ACCESSORS
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_rasterize_edges (pixman_image_t *image,
|
||||
pixman_edge_t * l,
|
||||
pixman_edge_t * r,
|
||||
pixman_fixed_t t,
|
||||
pixman_fixed_t b)
|
||||
{
|
||||
return_if_fail (image->type == BITS);
|
||||
return_if_fail (PIXMAN_FORMAT_TYPE (image->bits.format) == PIXMAN_TYPE_A);
|
||||
|
||||
if (image->bits.read_func || image->bits.write_func)
|
||||
pixman_rasterize_edges_accessors (image, l, r, t, b);
|
||||
else
|
||||
pixman_rasterize_edges_no_accessors (image, l, r, t, b);
|
||||
}
|
||||
|
||||
#endif
|
||||
2590
gfx/cairo/libpixman/src/pixman-fast-path.c
Normal file
2590
gfx/cairo/libpixman/src/pixman-fast-path.c
Normal file
File diff suppressed because it is too large
Load diff
1022
gfx/cairo/libpixman/src/pixman-fast-path.h
Normal file
1022
gfx/cairo/libpixman/src/pixman-fast-path.h
Normal file
File diff suppressed because it is too large
Load diff
350
gfx/cairo/libpixman/src/pixman-filter.c
Normal file
350
gfx/cairo/libpixman/src/pixman-filter.c
Normal file
|
|
@ -0,0 +1,350 @@
|
|||
/*
|
||||
* Copyright 2012, Red Hat, Inc.
|
||||
* Copyright 2012, Soren Sandmann
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Author: Soren Sandmann <soren.sandmann@gmail.com>
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include "pixman-private.h"
|
||||
|
||||
typedef double (* kernel_func_t) (double x);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
pixman_kernel_t kernel;
|
||||
kernel_func_t func;
|
||||
double width;
|
||||
} filter_info_t;
|
||||
|
||||
static double
|
||||
impulse_kernel (double x)
|
||||
{
|
||||
return (x == 0.0)? 1.0 : 0.0;
|
||||
}
|
||||
|
||||
static double
|
||||
box_kernel (double x)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static double
|
||||
linear_kernel (double x)
|
||||
{
|
||||
return 1 - fabs (x);
|
||||
}
|
||||
|
||||
static double
|
||||
gaussian_kernel (double x)
|
||||
{
|
||||
#define SQRT2 (1.4142135623730950488016887242096980785696718753769480)
|
||||
#define SIGMA (SQRT2 / 2.0)
|
||||
|
||||
return exp (- x * x / (2 * SIGMA * SIGMA)) / (SIGMA * sqrt (2.0 * M_PI));
|
||||
}
|
||||
|
||||
static double
|
||||
sinc (double x)
|
||||
{
|
||||
if (x == 0.0)
|
||||
return 1.0;
|
||||
else
|
||||
return sin (M_PI * x) / (M_PI * x);
|
||||
}
|
||||
|
||||
static double
|
||||
lanczos (double x, int n)
|
||||
{
|
||||
return sinc (x) * sinc (x * (1.0 / n));
|
||||
}
|
||||
|
||||
static double
|
||||
lanczos2_kernel (double x)
|
||||
{
|
||||
return lanczos (x, 2);
|
||||
}
|
||||
|
||||
static double
|
||||
lanczos3_kernel (double x)
|
||||
{
|
||||
return lanczos (x, 3);
|
||||
}
|
||||
|
||||
static double
|
||||
nice_kernel (double x)
|
||||
{
|
||||
return lanczos3_kernel (x * 0.75);
|
||||
}
|
||||
|
||||
static double
|
||||
general_cubic (double x, double B, double C)
|
||||
{
|
||||
double ax = fabs(x);
|
||||
|
||||
if (ax < 1)
|
||||
{
|
||||
return ((12 - 9 * B - 6 * C) * ax * ax * ax +
|
||||
(-18 + 12 * B + 6 * C) * ax * ax + (6 - 2 * B)) / 6;
|
||||
}
|
||||
else if (ax >= 1 && ax < 2)
|
||||
{
|
||||
return ((-B - 6 * C) * ax * ax * ax +
|
||||
(6 * B + 30 * C) * ax * ax + (-12 * B - 48 * C) *
|
||||
ax + (8 * B + 24 * C)) / 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static double
|
||||
cubic_kernel (double x)
|
||||
{
|
||||
/* This is the Mitchell-Netravali filter.
|
||||
*
|
||||
* (0.0, 0.5) would give us the Catmull-Rom spline,
|
||||
* but that one seems to be indistinguishable from Lanczos2.
|
||||
*/
|
||||
return general_cubic (x, 1/3.0, 1/3.0);
|
||||
}
|
||||
|
||||
static const filter_info_t filters[] =
|
||||
{
|
||||
{ PIXMAN_KERNEL_IMPULSE, impulse_kernel, 0.0 },
|
||||
{ PIXMAN_KERNEL_BOX, box_kernel, 1.0 },
|
||||
{ PIXMAN_KERNEL_LINEAR, linear_kernel, 2.0 },
|
||||
{ PIXMAN_KERNEL_CUBIC, cubic_kernel, 4.0 },
|
||||
{ PIXMAN_KERNEL_GAUSSIAN, gaussian_kernel, 6 * SIGMA },
|
||||
{ PIXMAN_KERNEL_LANCZOS2, lanczos2_kernel, 4.0 },
|
||||
{ PIXMAN_KERNEL_LANCZOS3, lanczos3_kernel, 6.0 },
|
||||
{ PIXMAN_KERNEL_LANCZOS3_STRETCHED, nice_kernel, 8.0 },
|
||||
};
|
||||
|
||||
/* This function scales @kernel2 by @scale, then
|
||||
* aligns @x1 in @kernel1 with @x2 in @kernel2 and
|
||||
* and integrates the product of the kernels across @width.
|
||||
*
|
||||
* This function assumes that the intervals are within
|
||||
* the kernels in question. E.g., the caller must not
|
||||
* try to integrate a linear kernel ouside of [-1:1]
|
||||
*/
|
||||
static double
|
||||
integral (pixman_kernel_t kernel1, double x1,
|
||||
pixman_kernel_t kernel2, double scale, double x2,
|
||||
double width)
|
||||
{
|
||||
/* If the integration interval crosses zero, break it into
|
||||
* two separate integrals. This ensures that filters such
|
||||
* as LINEAR that are not differentiable at 0 will still
|
||||
* integrate properly.
|
||||
*/
|
||||
if (x1 < 0 && x1 + width > 0)
|
||||
{
|
||||
return
|
||||
integral (kernel1, x1, kernel2, scale, x2, - x1) +
|
||||
integral (kernel1, 0, kernel2, scale, x2 - x1, width + x1);
|
||||
}
|
||||
else if (x2 < 0 && x2 + width > 0)
|
||||
{
|
||||
return
|
||||
integral (kernel1, x1, kernel2, scale, x2, - x2) +
|
||||
integral (kernel1, x1 - x2, kernel2, scale, 0, width + x2);
|
||||
}
|
||||
else if (kernel1 == PIXMAN_KERNEL_IMPULSE)
|
||||
{
|
||||
assert (width == 0.0);
|
||||
return filters[kernel2].func (x2 * scale);
|
||||
}
|
||||
else if (kernel2 == PIXMAN_KERNEL_IMPULSE)
|
||||
{
|
||||
assert (width == 0.0);
|
||||
return filters[kernel1].func (x1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Integration via Simpson's rule */
|
||||
#define N_SEGMENTS 128
|
||||
#define SAMPLE(a1, a2) \
|
||||
(filters[kernel1].func ((a1)) * filters[kernel2].func ((a2) * scale))
|
||||
|
||||
double s = 0.0;
|
||||
double h = width / (double)N_SEGMENTS;
|
||||
int i;
|
||||
|
||||
s = SAMPLE (x1, x2);
|
||||
|
||||
for (i = 1; i < N_SEGMENTS; i += 2)
|
||||
{
|
||||
double a1 = x1 + h * i;
|
||||
double a2 = x2 + h * i;
|
||||
|
||||
s += 2 * SAMPLE (a1, a2);
|
||||
|
||||
if (i >= 2 && i < N_SEGMENTS - 1)
|
||||
s += 4 * SAMPLE (a1, a2);
|
||||
}
|
||||
|
||||
s += SAMPLE (x1 + width, x2 + width);
|
||||
|
||||
return h * s * (1.0 / 3.0);
|
||||
}
|
||||
}
|
||||
|
||||
static pixman_fixed_t *
|
||||
create_1d_filter (int *width,
|
||||
pixman_kernel_t reconstruct,
|
||||
pixman_kernel_t sample,
|
||||
double scale,
|
||||
int n_phases)
|
||||
{
|
||||
pixman_fixed_t *params, *p;
|
||||
double step;
|
||||
double size;
|
||||
int i;
|
||||
|
||||
size = scale * filters[sample].width + filters[reconstruct].width;
|
||||
*width = ceil (size);
|
||||
|
||||
p = params = malloc (*width * n_phases * sizeof (pixman_fixed_t));
|
||||
if (!params)
|
||||
return NULL;
|
||||
|
||||
step = 1.0 / n_phases;
|
||||
|
||||
for (i = 0; i < n_phases; ++i)
|
||||
{
|
||||
double frac = step / 2.0 + i * step;
|
||||
pixman_fixed_t new_total;
|
||||
int x, x1, x2;
|
||||
double total;
|
||||
|
||||
/* Sample convolution of reconstruction and sampling
|
||||
* filter. See rounding.txt regarding the rounding
|
||||
* and sample positions.
|
||||
*/
|
||||
|
||||
x1 = ceil (frac - *width / 2.0 - 0.5);
|
||||
x2 = x1 + *width;
|
||||
|
||||
total = 0;
|
||||
for (x = x1; x < x2; ++x)
|
||||
{
|
||||
double pos = x + 0.5 - frac;
|
||||
double rlow = - filters[reconstruct].width / 2.0;
|
||||
double rhigh = rlow + filters[reconstruct].width;
|
||||
double slow = pos - scale * filters[sample].width / 2.0;
|
||||
double shigh = slow + scale * filters[sample].width;
|
||||
double c = 0.0;
|
||||
double ilow, ihigh;
|
||||
|
||||
if (rhigh >= slow && rlow <= shigh)
|
||||
{
|
||||
ilow = MAX (slow, rlow);
|
||||
ihigh = MIN (shigh, rhigh);
|
||||
|
||||
c = integral (reconstruct, ilow,
|
||||
sample, 1.0 / scale, ilow - pos,
|
||||
ihigh - ilow);
|
||||
}
|
||||
|
||||
total += c;
|
||||
*p++ = (pixman_fixed_t)(c * 65535.0 + 0.5);
|
||||
}
|
||||
|
||||
/* Normalize */
|
||||
p -= *width;
|
||||
total = 1 / total;
|
||||
new_total = 0;
|
||||
for (x = x1; x < x2; ++x)
|
||||
{
|
||||
pixman_fixed_t t = (*p) * total + 0.5;
|
||||
|
||||
new_total += t;
|
||||
*p++ = t;
|
||||
}
|
||||
|
||||
if (new_total != pixman_fixed_1)
|
||||
*(p - *width / 2) += (pixman_fixed_1 - new_total);
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
/* Create the parameter list for a SEPARABLE_CONVOLUTION filter
|
||||
* with the given kernels and scale parameters
|
||||
*/
|
||||
PIXMAN_EXPORT pixman_fixed_t *
|
||||
pixman_filter_create_separable_convolution (int *n_values,
|
||||
pixman_fixed_t scale_x,
|
||||
pixman_fixed_t scale_y,
|
||||
pixman_kernel_t reconstruct_x,
|
||||
pixman_kernel_t reconstruct_y,
|
||||
pixman_kernel_t sample_x,
|
||||
pixman_kernel_t sample_y,
|
||||
int subsample_bits_x,
|
||||
int subsample_bits_y)
|
||||
{
|
||||
double sx = fabs (pixman_fixed_to_double (scale_x));
|
||||
double sy = fabs (pixman_fixed_to_double (scale_y));
|
||||
pixman_fixed_t *horz = NULL, *vert = NULL, *params = NULL;
|
||||
int subsample_x, subsample_y;
|
||||
int width, height;
|
||||
|
||||
subsample_x = (1 << subsample_bits_x);
|
||||
subsample_y = (1 << subsample_bits_y);
|
||||
|
||||
horz = create_1d_filter (&width, reconstruct_x, sample_x, sx, subsample_x);
|
||||
vert = create_1d_filter (&height, reconstruct_y, sample_y, sy, subsample_y);
|
||||
|
||||
if (!horz || !vert)
|
||||
goto out;
|
||||
|
||||
*n_values = 4 + width * subsample_x + height * subsample_y;
|
||||
|
||||
params = malloc (*n_values * sizeof (pixman_fixed_t));
|
||||
if (!params)
|
||||
goto out;
|
||||
|
||||
params[0] = pixman_int_to_fixed (width);
|
||||
params[1] = pixman_int_to_fixed (height);
|
||||
params[2] = pixman_int_to_fixed (subsample_bits_x);
|
||||
params[3] = pixman_int_to_fixed (subsample_bits_y);
|
||||
|
||||
memcpy (params + 4, horz,
|
||||
width * subsample_x * sizeof (pixman_fixed_t));
|
||||
memcpy (params + 4 + width * subsample_x, vert,
|
||||
height * subsample_y * sizeof (pixman_fixed_t));
|
||||
|
||||
out:
|
||||
free (horz);
|
||||
free (vert);
|
||||
|
||||
return params;
|
||||
}
|
||||
243
gfx/cairo/libpixman/src/pixman-general.c
Normal file
243
gfx/cairo/libpixman/src/pixman-general.c
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
* Copyright © 2009 Red Hat, Inc.
|
||||
* Copyright © 2000 SuSE, Inc.
|
||||
* Copyright © 2007 Red Hat, Inc.
|
||||
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
|
||||
* 2005 Lars Knoll & Zack Rusin, Trolltech
|
||||
* 2008 Aaron Plattner, NVIDIA Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Red Hat not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. Red Hat makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "pixman-private.h"
|
||||
|
||||
static pixman_bool_t
|
||||
general_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
|
||||
{
|
||||
pixman_image_t *image = iter->image;
|
||||
|
||||
if (image->type == LINEAR)
|
||||
_pixman_linear_gradient_iter_init (image, iter);
|
||||
else if (image->type == RADIAL)
|
||||
_pixman_radial_gradient_iter_init (image, iter);
|
||||
else if (image->type == CONICAL)
|
||||
_pixman_conical_gradient_iter_init (image, iter);
|
||||
else if (image->type == BITS)
|
||||
_pixman_bits_image_src_iter_init (image, iter);
|
||||
else if (image->type == SOLID)
|
||||
_pixman_log_error (FUNC, "Solid image not handled by noop");
|
||||
else
|
||||
_pixman_log_error (FUNC, "Pixman bug: unknown image type\n");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static pixman_bool_t
|
||||
general_dest_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
|
||||
{
|
||||
if (iter->image->type == BITS)
|
||||
{
|
||||
_pixman_bits_image_dest_iter_init (iter->image, iter);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
_pixman_log_error (FUNC, "Trying to write to a non-writable image");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct op_info_t op_info_t;
|
||||
struct op_info_t
|
||||
{
|
||||
uint8_t src, dst;
|
||||
};
|
||||
|
||||
#define ITER_IGNORE_BOTH \
|
||||
(ITER_IGNORE_ALPHA | ITER_IGNORE_RGB | ITER_LOCALIZED_ALPHA)
|
||||
|
||||
static const op_info_t op_flags[PIXMAN_N_OPERATORS] =
|
||||
{
|
||||
/* Src Dst */
|
||||
{ ITER_IGNORE_BOTH, ITER_IGNORE_BOTH }, /* CLEAR */
|
||||
{ ITER_LOCALIZED_ALPHA, ITER_IGNORE_BOTH }, /* SRC */
|
||||
{ ITER_IGNORE_BOTH, ITER_LOCALIZED_ALPHA }, /* DST */
|
||||
{ 0, ITER_LOCALIZED_ALPHA }, /* OVER */
|
||||
{ ITER_LOCALIZED_ALPHA, 0 }, /* OVER_REVERSE */
|
||||
{ ITER_LOCALIZED_ALPHA, ITER_IGNORE_RGB }, /* IN */
|
||||
{ ITER_IGNORE_RGB, ITER_LOCALIZED_ALPHA }, /* IN_REVERSE */
|
||||
{ ITER_LOCALIZED_ALPHA, ITER_IGNORE_RGB }, /* OUT */
|
||||
{ ITER_IGNORE_RGB, ITER_LOCALIZED_ALPHA }, /* OUT_REVERSE */
|
||||
{ 0, 0 }, /* ATOP */
|
||||
{ 0, 0 }, /* ATOP_REVERSE */
|
||||
{ 0, 0 }, /* XOR */
|
||||
{ ITER_LOCALIZED_ALPHA, ITER_LOCALIZED_ALPHA }, /* ADD */
|
||||
{ 0, 0 }, /* SATURATE */
|
||||
};
|
||||
|
||||
#define SCANLINE_BUFFER_LENGTH 8192
|
||||
|
||||
static void
|
||||
general_composite_rect (pixman_implementation_t *imp,
|
||||
pixman_composite_info_t *info)
|
||||
{
|
||||
PIXMAN_COMPOSITE_ARGS (info);
|
||||
uint64_t stack_scanline_buffer[(SCANLINE_BUFFER_LENGTH * 3 + 7) / 8];
|
||||
uint8_t *scanline_buffer = (uint8_t *) stack_scanline_buffer;
|
||||
uint8_t *src_buffer, *mask_buffer, *dest_buffer;
|
||||
pixman_iter_t src_iter, mask_iter, dest_iter;
|
||||
pixman_combine_32_func_t compose;
|
||||
pixman_bool_t component_alpha;
|
||||
iter_flags_t narrow, src_iter_flags;
|
||||
iter_flags_t rgb16;
|
||||
int Bpp;
|
||||
int i;
|
||||
|
||||
if ((src_image->common.flags & FAST_PATH_NARROW_FORMAT) &&
|
||||
(!mask_image || mask_image->common.flags & FAST_PATH_NARROW_FORMAT) &&
|
||||
(dest_image->common.flags & FAST_PATH_NARROW_FORMAT))
|
||||
{
|
||||
narrow = ITER_NARROW;
|
||||
Bpp = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
narrow = 0;
|
||||
Bpp = 16;
|
||||
}
|
||||
|
||||
// XXX: This special casing is bad. Ideally, we'd keep the general code general perhaps
|
||||
// by having it deal more specifically with different intermediate formats
|
||||
if (
|
||||
(dest_image->common.flags & FAST_PATH_16_FORMAT && (src_image->type == LINEAR || src_image->type == RADIAL)) &&
|
||||
( op == PIXMAN_OP_SRC ||
|
||||
(op == PIXMAN_OP_OVER && (src_image->common.flags & FAST_PATH_IS_OPAQUE))
|
||||
)
|
||||
) {
|
||||
rgb16 = ITER_16;
|
||||
} else {
|
||||
rgb16 = 0;
|
||||
}
|
||||
|
||||
|
||||
if (width * Bpp > SCANLINE_BUFFER_LENGTH)
|
||||
{
|
||||
scanline_buffer = pixman_malloc_abc (width, 3, Bpp);
|
||||
|
||||
if (!scanline_buffer)
|
||||
return;
|
||||
}
|
||||
|
||||
src_buffer = scanline_buffer;
|
||||
mask_buffer = src_buffer + width * Bpp;
|
||||
dest_buffer = mask_buffer + width * Bpp;
|
||||
|
||||
if (!narrow)
|
||||
{
|
||||
/* To make sure there aren't any NANs in the buffers */
|
||||
memset (src_buffer, 0, width * Bpp);
|
||||
memset (mask_buffer, 0, width * Bpp);
|
||||
memset (dest_buffer, 0, width * Bpp);
|
||||
}
|
||||
|
||||
/* src iter */
|
||||
src_iter_flags = narrow | op_flags[op].src | rgb16;
|
||||
|
||||
_pixman_implementation_src_iter_init (imp->toplevel, &src_iter, src_image,
|
||||
src_x, src_y, width, height,
|
||||
src_buffer, src_iter_flags, info->src_flags);
|
||||
|
||||
/* mask iter */
|
||||
if ((src_iter_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) ==
|
||||
(ITER_IGNORE_ALPHA | ITER_IGNORE_RGB))
|
||||
{
|
||||
/* If it doesn't matter what the source is, then it doesn't matter
|
||||
* what the mask is
|
||||
*/
|
||||
mask_image = NULL;
|
||||
}
|
||||
|
||||
component_alpha =
|
||||
mask_image &&
|
||||
mask_image->common.type == BITS &&
|
||||
mask_image->common.component_alpha &&
|
||||
PIXMAN_FORMAT_RGB (mask_image->bits.format);
|
||||
|
||||
_pixman_implementation_src_iter_init (
|
||||
imp->toplevel, &mask_iter, mask_image, mask_x, mask_y, width, height,
|
||||
mask_buffer, narrow | (component_alpha? 0 : ITER_IGNORE_RGB), info->mask_flags);
|
||||
|
||||
/* dest iter */
|
||||
_pixman_implementation_dest_iter_init (
|
||||
imp->toplevel, &dest_iter, dest_image, dest_x, dest_y, width, height,
|
||||
dest_buffer, narrow | op_flags[op].dst | rgb16, info->dest_flags);
|
||||
|
||||
compose = _pixman_implementation_lookup_combiner (
|
||||
imp->toplevel, op, component_alpha, narrow, !!rgb16);
|
||||
|
||||
for (i = 0; i < height; ++i)
|
||||
{
|
||||
uint32_t *s, *m, *d;
|
||||
|
||||
m = mask_iter.get_scanline (&mask_iter, NULL);
|
||||
s = src_iter.get_scanline (&src_iter, m);
|
||||
d = dest_iter.get_scanline (&dest_iter, NULL);
|
||||
|
||||
compose (imp->toplevel, op, d, s, m, width);
|
||||
|
||||
dest_iter.write_back (&dest_iter);
|
||||
}
|
||||
|
||||
if (scanline_buffer != (uint8_t *) stack_scanline_buffer)
|
||||
free (scanline_buffer);
|
||||
}
|
||||
|
||||
static const pixman_fast_path_t general_fast_path[] =
|
||||
{
|
||||
{ PIXMAN_OP_any, PIXMAN_any, 0, PIXMAN_any, 0, PIXMAN_any, 0, general_composite_rect },
|
||||
{ PIXMAN_OP_NONE }
|
||||
};
|
||||
|
||||
pixman_implementation_t *
|
||||
_pixman_implementation_create_general (void)
|
||||
{
|
||||
pixman_implementation_t *imp = _pixman_implementation_create (NULL, general_fast_path);
|
||||
|
||||
_pixman_setup_combiner_functions_16 (imp);
|
||||
_pixman_setup_combiner_functions_32 (imp);
|
||||
_pixman_setup_combiner_functions_float (imp);
|
||||
|
||||
imp->src_iter_init = general_src_iter_init;
|
||||
imp->dest_iter_init = general_dest_iter_init;
|
||||
|
||||
return imp;
|
||||
}
|
||||
|
||||
670
gfx/cairo/libpixman/src/pixman-glyph.c
Normal file
670
gfx/cairo/libpixman/src/pixman-glyph.c
Normal file
|
|
@ -0,0 +1,670 @@
|
|||
/*
|
||||
* Copyright 2010, 2012, Soren Sandmann <sandmann@cs.au.dk>
|
||||
* Copyright 2010, 2011, 2012, Red Hat, Inc
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Author: Soren Sandmann <sandmann@cs.au.dk>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include "pixman-private.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct glyph_metrics_t glyph_metrics_t;
|
||||
typedef struct glyph_t glyph_t;
|
||||
|
||||
#define TOMBSTONE ((glyph_t *)0x1)
|
||||
|
||||
/* XXX: These numbers are arbitrary---we've never done any measurements.
|
||||
*/
|
||||
#define N_GLYPHS_HIGH_WATER (16384)
|
||||
#define N_GLYPHS_LOW_WATER (8192)
|
||||
#define HASH_SIZE (2 * N_GLYPHS_HIGH_WATER)
|
||||
#define HASH_MASK (HASH_SIZE - 1)
|
||||
|
||||
struct glyph_t
|
||||
{
|
||||
void * font_key;
|
||||
void * glyph_key;
|
||||
int origin_x;
|
||||
int origin_y;
|
||||
pixman_image_t * image;
|
||||
pixman_link_t mru_link;
|
||||
};
|
||||
|
||||
struct pixman_glyph_cache_t
|
||||
{
|
||||
int n_glyphs;
|
||||
int n_tombstones;
|
||||
int freeze_count;
|
||||
pixman_list_t mru;
|
||||
glyph_t * glyphs[HASH_SIZE];
|
||||
};
|
||||
|
||||
static void
|
||||
free_glyph (glyph_t *glyph)
|
||||
{
|
||||
pixman_list_unlink (&glyph->mru_link);
|
||||
pixman_image_unref (glyph->image);
|
||||
free (glyph);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
hash (const void *font_key, const void *glyph_key)
|
||||
{
|
||||
size_t key = (size_t)font_key + (size_t)glyph_key;
|
||||
|
||||
/* This hash function is based on one found on Thomas Wang's
|
||||
* web page at
|
||||
*
|
||||
* http://www.concentric.net/~Ttwang/tech/inthash.htm
|
||||
*
|
||||
*/
|
||||
key = (key << 15) - key - 1;
|
||||
key = key ^ (key >> 12);
|
||||
key = key + (key << 2);
|
||||
key = key ^ (key >> 4);
|
||||
key = key + (key << 3) + (key << 11);
|
||||
key = key ^ (key >> 16);
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
static glyph_t *
|
||||
lookup_glyph (pixman_glyph_cache_t *cache,
|
||||
void *font_key,
|
||||
void *glyph_key)
|
||||
{
|
||||
unsigned idx;
|
||||
glyph_t *g;
|
||||
|
||||
idx = hash (font_key, glyph_key);
|
||||
while ((g = cache->glyphs[idx++ & HASH_MASK]))
|
||||
{
|
||||
if (g != TOMBSTONE &&
|
||||
g->font_key == font_key &&
|
||||
g->glyph_key == glyph_key)
|
||||
{
|
||||
return g;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
insert_glyph (pixman_glyph_cache_t *cache,
|
||||
glyph_t *glyph)
|
||||
{
|
||||
unsigned idx;
|
||||
glyph_t **loc;
|
||||
|
||||
idx = hash (glyph->font_key, glyph->glyph_key);
|
||||
|
||||
/* Note: we assume that there is room in the table. If there isn't,
|
||||
* this will be an infinite loop.
|
||||
*/
|
||||
do
|
||||
{
|
||||
loc = &cache->glyphs[idx++ & HASH_MASK];
|
||||
} while (*loc && *loc != TOMBSTONE);
|
||||
|
||||
if (*loc == TOMBSTONE)
|
||||
cache->n_tombstones--;
|
||||
cache->n_glyphs++;
|
||||
|
||||
*loc = glyph;
|
||||
}
|
||||
|
||||
static void
|
||||
remove_glyph (pixman_glyph_cache_t *cache,
|
||||
glyph_t *glyph)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
idx = hash (glyph->font_key, glyph->glyph_key);
|
||||
while (cache->glyphs[idx & HASH_MASK] != glyph)
|
||||
idx++;
|
||||
|
||||
cache->glyphs[idx & HASH_MASK] = TOMBSTONE;
|
||||
cache->n_tombstones++;
|
||||
cache->n_glyphs--;
|
||||
|
||||
/* Eliminate tombstones if possible */
|
||||
if (cache->glyphs[(idx + 1) & HASH_MASK] == NULL)
|
||||
{
|
||||
while (cache->glyphs[idx & HASH_MASK] == TOMBSTONE)
|
||||
{
|
||||
cache->glyphs[idx & HASH_MASK] = NULL;
|
||||
cache->n_tombstones--;
|
||||
idx--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clear_table (pixman_glyph_cache_t *cache)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < HASH_SIZE; ++i)
|
||||
{
|
||||
glyph_t *glyph = cache->glyphs[i];
|
||||
|
||||
if (glyph && glyph != TOMBSTONE)
|
||||
free_glyph (glyph);
|
||||
|
||||
cache->glyphs[i] = NULL;
|
||||
}
|
||||
|
||||
cache->n_glyphs = 0;
|
||||
cache->n_tombstones = 0;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT pixman_glyph_cache_t *
|
||||
pixman_glyph_cache_create (void)
|
||||
{
|
||||
pixman_glyph_cache_t *cache;
|
||||
|
||||
if (!(cache = malloc (sizeof *cache)))
|
||||
return NULL;
|
||||
|
||||
memset (cache->glyphs, 0, sizeof (cache->glyphs));
|
||||
cache->n_glyphs = 0;
|
||||
cache->n_tombstones = 0;
|
||||
cache->freeze_count = 0;
|
||||
|
||||
pixman_list_init (&cache->mru);
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_glyph_cache_destroy (pixman_glyph_cache_t *cache)
|
||||
{
|
||||
return_if_fail (cache->freeze_count == 0);
|
||||
|
||||
clear_table (cache);
|
||||
|
||||
free (cache);
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_glyph_cache_freeze (pixman_glyph_cache_t *cache)
|
||||
{
|
||||
cache->freeze_count++;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_glyph_cache_thaw (pixman_glyph_cache_t *cache)
|
||||
{
|
||||
if (--cache->freeze_count == 0 &&
|
||||
cache->n_glyphs + cache->n_tombstones > N_GLYPHS_HIGH_WATER)
|
||||
{
|
||||
if (cache->n_tombstones > N_GLYPHS_HIGH_WATER)
|
||||
{
|
||||
/* More than half the entries are
|
||||
* tombstones. Just dump the whole table.
|
||||
*/
|
||||
clear_table (cache);
|
||||
}
|
||||
|
||||
while (cache->n_glyphs > N_GLYPHS_LOW_WATER)
|
||||
{
|
||||
glyph_t *glyph = CONTAINER_OF (glyph_t, mru_link, cache->mru.tail);
|
||||
|
||||
remove_glyph (cache, glyph);
|
||||
free_glyph (glyph);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT const void *
|
||||
pixman_glyph_cache_lookup (pixman_glyph_cache_t *cache,
|
||||
void *font_key,
|
||||
void *glyph_key)
|
||||
{
|
||||
return lookup_glyph (cache, font_key, glyph_key);
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT const void *
|
||||
pixman_glyph_cache_insert (pixman_glyph_cache_t *cache,
|
||||
void *font_key,
|
||||
void *glyph_key,
|
||||
int origin_x,
|
||||
int origin_y,
|
||||
pixman_image_t *image)
|
||||
{
|
||||
glyph_t *glyph;
|
||||
int32_t width, height;
|
||||
|
||||
return_val_if_fail (cache->freeze_count > 0, NULL);
|
||||
return_val_if_fail (image->type == BITS, NULL);
|
||||
|
||||
width = image->bits.width;
|
||||
height = image->bits.height;
|
||||
|
||||
if (cache->n_glyphs >= HASH_SIZE)
|
||||
return NULL;
|
||||
|
||||
if (!(glyph = malloc (sizeof *glyph)))
|
||||
return NULL;
|
||||
|
||||
glyph->font_key = font_key;
|
||||
glyph->glyph_key = glyph_key;
|
||||
glyph->origin_x = origin_x;
|
||||
glyph->origin_y = origin_y;
|
||||
|
||||
if (!(glyph->image = pixman_image_create_bits (
|
||||
image->bits.format, width, height, NULL, -1)))
|
||||
{
|
||||
free (glyph);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pixman_image_composite32 (PIXMAN_OP_SRC,
|
||||
image, NULL, glyph->image, 0, 0, 0, 0, 0, 0,
|
||||
width, height);
|
||||
|
||||
if (PIXMAN_FORMAT_A (glyph->image->bits.format) != 0 &&
|
||||
PIXMAN_FORMAT_RGB (glyph->image->bits.format) != 0)
|
||||
{
|
||||
pixman_image_set_component_alpha (glyph->image, TRUE);
|
||||
}
|
||||
|
||||
pixman_list_prepend (&cache->mru, &glyph->mru_link);
|
||||
|
||||
_pixman_image_validate (glyph->image);
|
||||
insert_glyph (cache, glyph);
|
||||
|
||||
return glyph;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_glyph_cache_remove (pixman_glyph_cache_t *cache,
|
||||
void *font_key,
|
||||
void *glyph_key)
|
||||
{
|
||||
glyph_t *glyph;
|
||||
|
||||
if ((glyph = lookup_glyph (cache, font_key, glyph_key)))
|
||||
{
|
||||
remove_glyph (cache, glyph);
|
||||
|
||||
free_glyph (glyph);
|
||||
}
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_glyph_get_extents (pixman_glyph_cache_t *cache,
|
||||
int n_glyphs,
|
||||
pixman_glyph_t *glyphs,
|
||||
pixman_box32_t *extents)
|
||||
{
|
||||
int i;
|
||||
|
||||
extents->x1 = extents->y1 = INT32_MAX;
|
||||
extents->x2 = extents->y2 = INT32_MIN;
|
||||
|
||||
for (i = 0; i < n_glyphs; ++i)
|
||||
{
|
||||
glyph_t *glyph = (glyph_t *)glyphs[i].glyph;
|
||||
int x1, y1, x2, y2;
|
||||
|
||||
x1 = glyphs[i].x - glyph->origin_x;
|
||||
y1 = glyphs[i].y - glyph->origin_y;
|
||||
x2 = glyphs[i].x - glyph->origin_x + glyph->image->bits.width;
|
||||
y2 = glyphs[i].y - glyph->origin_y + glyph->image->bits.height;
|
||||
|
||||
if (x1 < extents->x1)
|
||||
extents->x1 = x1;
|
||||
if (y1 < extents->y1)
|
||||
extents->y1 = y1;
|
||||
if (x2 > extents->x2)
|
||||
extents->x2 = x2;
|
||||
if (y2 > extents->y2)
|
||||
extents->y2 = y2;
|
||||
}
|
||||
}
|
||||
|
||||
/* This function returns a format that is suitable for use as a mask for the
|
||||
* set of glyphs in question.
|
||||
*/
|
||||
PIXMAN_EXPORT pixman_format_code_t
|
||||
pixman_glyph_get_mask_format (pixman_glyph_cache_t *cache,
|
||||
int n_glyphs,
|
||||
const pixman_glyph_t *glyphs)
|
||||
{
|
||||
pixman_format_code_t format = PIXMAN_a1;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_glyphs; ++i)
|
||||
{
|
||||
const glyph_t *glyph = glyphs[i].glyph;
|
||||
pixman_format_code_t glyph_format = glyph->image->bits.format;
|
||||
|
||||
if (PIXMAN_FORMAT_TYPE (glyph_format) == PIXMAN_TYPE_A)
|
||||
{
|
||||
if (PIXMAN_FORMAT_A (glyph_format) > PIXMAN_FORMAT_A (format))
|
||||
format = glyph_format;
|
||||
}
|
||||
else
|
||||
{
|
||||
return PIXMAN_a8r8g8b8;
|
||||
}
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
static pixman_bool_t
|
||||
box32_intersect (pixman_box32_t *dest,
|
||||
const pixman_box32_t *box1,
|
||||
const pixman_box32_t *box2)
|
||||
{
|
||||
dest->x1 = MAX (box1->x1, box2->x1);
|
||||
dest->y1 = MAX (box1->y1, box2->y1);
|
||||
dest->x2 = MIN (box1->x2, box2->x2);
|
||||
dest->y2 = MIN (box1->y2, box2->y2);
|
||||
|
||||
return dest->x2 > dest->x1 && dest->y2 > dest->y1;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_composite_glyphs_no_mask (pixman_op_t op,
|
||||
pixman_image_t *src,
|
||||
pixman_image_t *dest,
|
||||
int32_t src_x,
|
||||
int32_t src_y,
|
||||
int32_t dest_x,
|
||||
int32_t dest_y,
|
||||
pixman_glyph_cache_t *cache,
|
||||
int n_glyphs,
|
||||
const pixman_glyph_t *glyphs)
|
||||
{
|
||||
pixman_region32_t region;
|
||||
pixman_format_code_t glyph_format = PIXMAN_null;
|
||||
uint32_t glyph_flags = 0;
|
||||
pixman_format_code_t dest_format;
|
||||
uint32_t dest_flags;
|
||||
pixman_composite_func_t func = NULL;
|
||||
pixman_implementation_t *implementation = NULL;
|
||||
pixman_composite_info_t info;
|
||||
int i;
|
||||
|
||||
_pixman_image_validate (src);
|
||||
_pixman_image_validate (dest);
|
||||
|
||||
dest_format = dest->common.extended_format_code;
|
||||
dest_flags = dest->common.flags;
|
||||
|
||||
pixman_region32_init (®ion);
|
||||
if (!_pixman_compute_composite_region32 (
|
||||
®ion,
|
||||
src, NULL, dest,
|
||||
src_x - dest_x, src_y - dest_y, 0, 0, 0, 0,
|
||||
dest->bits.width, dest->bits.height))
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
info.op = op;
|
||||
info.src_image = src;
|
||||
info.dest_image = dest;
|
||||
info.src_flags = src->common.flags;
|
||||
info.dest_flags = dest->common.flags;
|
||||
|
||||
for (i = 0; i < n_glyphs; ++i)
|
||||
{
|
||||
glyph_t *glyph = (glyph_t *)glyphs[i].glyph;
|
||||
pixman_image_t *glyph_img = glyph->image;
|
||||
pixman_box32_t glyph_box;
|
||||
pixman_box32_t *pbox;
|
||||
uint32_t extra = FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
|
||||
pixman_box32_t composite_box;
|
||||
int n;
|
||||
|
||||
glyph_box.x1 = dest_x + glyphs[i].x - glyph->origin_x;
|
||||
glyph_box.y1 = dest_y + glyphs[i].y - glyph->origin_y;
|
||||
glyph_box.x2 = glyph_box.x1 + glyph->image->bits.width;
|
||||
glyph_box.y2 = glyph_box.y1 + glyph->image->bits.height;
|
||||
|
||||
pbox = pixman_region32_rectangles (®ion, &n);
|
||||
|
||||
info.mask_image = glyph_img;
|
||||
|
||||
while (n--)
|
||||
{
|
||||
if (box32_intersect (&composite_box, pbox, &glyph_box))
|
||||
{
|
||||
if (glyph_img->common.extended_format_code != glyph_format ||
|
||||
glyph_img->common.flags != glyph_flags)
|
||||
{
|
||||
glyph_format = glyph_img->common.extended_format_code;
|
||||
glyph_flags = glyph_img->common.flags;
|
||||
|
||||
_pixman_implementation_lookup_composite (
|
||||
get_implementation(), op,
|
||||
src->common.extended_format_code, src->common.flags,
|
||||
glyph_format, glyph_flags | extra,
|
||||
dest_format, dest_flags,
|
||||
&implementation, &func);
|
||||
}
|
||||
|
||||
info.src_x = src_x + composite_box.x1 - dest_x;
|
||||
info.src_y = src_y + composite_box.y1 - dest_y;
|
||||
info.mask_x = composite_box.x1 - (dest_x + glyphs[i].x - glyph->origin_x);
|
||||
info.mask_y = composite_box.y1 - (dest_y + glyphs[i].y - glyph->origin_y);
|
||||
info.dest_x = composite_box.x1;
|
||||
info.dest_y = composite_box.y1;
|
||||
info.width = composite_box.x2 - composite_box.x1;
|
||||
info.height = composite_box.y2 - composite_box.y1;
|
||||
|
||||
info.mask_flags = glyph_flags;
|
||||
|
||||
func (implementation, &info);
|
||||
}
|
||||
|
||||
pbox++;
|
||||
}
|
||||
pixman_list_move_to_front (&cache->mru, &glyph->mru_link);
|
||||
}
|
||||
|
||||
out:
|
||||
pixman_region32_fini (®ion);
|
||||
}
|
||||
|
||||
static void
|
||||
add_glyphs (pixman_glyph_cache_t *cache,
|
||||
pixman_image_t *dest,
|
||||
int off_x, int off_y,
|
||||
int n_glyphs, const pixman_glyph_t *glyphs)
|
||||
{
|
||||
pixman_format_code_t glyph_format = PIXMAN_null;
|
||||
uint32_t glyph_flags = 0;
|
||||
pixman_composite_func_t func = NULL;
|
||||
pixman_implementation_t *implementation = NULL;
|
||||
pixman_format_code_t dest_format;
|
||||
uint32_t dest_flags;
|
||||
pixman_box32_t dest_box;
|
||||
pixman_composite_info_t info;
|
||||
pixman_image_t *white_img = NULL;
|
||||
pixman_bool_t white_src = FALSE;
|
||||
int i;
|
||||
|
||||
_pixman_image_validate (dest);
|
||||
|
||||
dest_format = dest->common.extended_format_code;
|
||||
dest_flags = dest->common.flags;
|
||||
|
||||
info.op = PIXMAN_OP_ADD;
|
||||
info.dest_image = dest;
|
||||
info.src_x = 0;
|
||||
info.src_y = 0;
|
||||
info.dest_flags = dest_flags;
|
||||
|
||||
dest_box.x1 = 0;
|
||||
dest_box.y1 = 0;
|
||||
dest_box.x2 = dest->bits.width;
|
||||
dest_box.y2 = dest->bits.height;
|
||||
|
||||
for (i = 0; i < n_glyphs; ++i)
|
||||
{
|
||||
glyph_t *glyph = (glyph_t *)glyphs[i].glyph;
|
||||
pixman_image_t *glyph_img = glyph->image;
|
||||
pixman_box32_t glyph_box;
|
||||
pixman_box32_t composite_box;
|
||||
|
||||
if (glyph_img->common.extended_format_code != glyph_format ||
|
||||
glyph_img->common.flags != glyph_flags)
|
||||
{
|
||||
pixman_format_code_t src_format, mask_format;
|
||||
|
||||
glyph_format = glyph_img->common.extended_format_code;
|
||||
glyph_flags = glyph_img->common.flags;
|
||||
|
||||
if (glyph_format == dest->bits.format)
|
||||
{
|
||||
src_format = glyph_format;
|
||||
mask_format = PIXMAN_null;
|
||||
info.src_flags = glyph_flags | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
|
||||
info.mask_flags = FAST_PATH_IS_OPAQUE;
|
||||
info.mask_image = NULL;
|
||||
white_src = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!white_img)
|
||||
{
|
||||
static const pixman_color_t white = { 0xffff, 0xffff, 0xffff, 0xffff };
|
||||
|
||||
if (!(white_img = pixman_image_create_solid_fill (&white)))
|
||||
goto out;
|
||||
|
||||
_pixman_image_validate (white_img);
|
||||
}
|
||||
|
||||
src_format = PIXMAN_solid;
|
||||
mask_format = glyph_format;
|
||||
info.src_flags = white_img->common.flags;
|
||||
info.mask_flags = glyph_flags | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
|
||||
info.src_image = white_img;
|
||||
white_src = TRUE;
|
||||
}
|
||||
|
||||
_pixman_implementation_lookup_composite (
|
||||
get_implementation(), PIXMAN_OP_ADD,
|
||||
src_format, info.src_flags,
|
||||
mask_format, info.mask_flags,
|
||||
dest_format, dest_flags,
|
||||
&implementation, &func);
|
||||
}
|
||||
|
||||
glyph_box.x1 = glyphs[i].x - glyph->origin_x + off_x;
|
||||
glyph_box.y1 = glyphs[i].y - glyph->origin_y + off_y;
|
||||
glyph_box.x2 = glyph_box.x1 + glyph->image->bits.width;
|
||||
glyph_box.y2 = glyph_box.y1 + glyph->image->bits.height;
|
||||
|
||||
if (box32_intersect (&composite_box, &glyph_box, &dest_box))
|
||||
{
|
||||
int src_x = composite_box.x1 - glyph_box.x1;
|
||||
int src_y = composite_box.y1 - glyph_box.y1;
|
||||
|
||||
if (white_src)
|
||||
info.mask_image = glyph_img;
|
||||
else
|
||||
info.src_image = glyph_img;
|
||||
|
||||
info.mask_x = info.src_x = src_x;
|
||||
info.mask_y = info.src_y = src_y;
|
||||
info.dest_x = composite_box.x1;
|
||||
info.dest_y = composite_box.y1;
|
||||
info.width = composite_box.x2 - composite_box.x1;
|
||||
info.height = composite_box.y2 - composite_box.y1;
|
||||
|
||||
func (implementation, &info);
|
||||
|
||||
pixman_list_move_to_front (&cache->mru, &glyph->mru_link);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (white_img)
|
||||
pixman_image_unref (white_img);
|
||||
}
|
||||
|
||||
/* Conceptually, for each glyph, (white IN glyph) is PIXMAN_OP_ADDed to an
|
||||
* infinitely big mask image at the position such that the glyph origin point
|
||||
* is positioned at the (glyphs[i].x, glyphs[i].y) point.
|
||||
*
|
||||
* Then (mask_x, mask_y) in the infinite mask and (src_x, src_y) in the source
|
||||
* image are both aligned with (dest_x, dest_y) in the destination image. Then
|
||||
* these three images are composited within the
|
||||
*
|
||||
* (dest_x, dest_y, dst_x + width, dst_y + height)
|
||||
*
|
||||
* rectangle.
|
||||
*
|
||||
* TODO:
|
||||
* - Trim the mask to the destination clip/image?
|
||||
* - Trim composite region based on sources, when the op ignores 0s.
|
||||
*/
|
||||
PIXMAN_EXPORT void
|
||||
pixman_composite_glyphs (pixman_op_t op,
|
||||
pixman_image_t *src,
|
||||
pixman_image_t *dest,
|
||||
pixman_format_code_t mask_format,
|
||||
int32_t src_x,
|
||||
int32_t src_y,
|
||||
int32_t mask_x,
|
||||
int32_t mask_y,
|
||||
int32_t dest_x,
|
||||
int32_t dest_y,
|
||||
int32_t width,
|
||||
int32_t height,
|
||||
pixman_glyph_cache_t *cache,
|
||||
int n_glyphs,
|
||||
const pixman_glyph_t *glyphs)
|
||||
{
|
||||
pixman_image_t *mask;
|
||||
|
||||
if (!(mask = pixman_image_create_bits (mask_format, width, height, NULL, -1)))
|
||||
return;
|
||||
|
||||
if (PIXMAN_FORMAT_A (mask_format) != 0 &&
|
||||
PIXMAN_FORMAT_RGB (mask_format) != 0)
|
||||
{
|
||||
pixman_image_set_component_alpha (mask, TRUE);
|
||||
}
|
||||
|
||||
add_glyphs (cache, mask, - mask_x, - mask_y, n_glyphs, glyphs);
|
||||
|
||||
pixman_image_composite32 (op, src, mask, dest,
|
||||
src_x, src_y,
|
||||
0, 0,
|
||||
dest_x, dest_y,
|
||||
width, height);
|
||||
|
||||
pixman_image_unref (mask);
|
||||
}
|
||||
172
gfx/cairo/libpixman/src/pixman-gradient-walker.c
Normal file
172
gfx/cairo/libpixman/src/pixman-gradient-walker.c
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
*
|
||||
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
|
||||
* 2005 Lars Knoll & Zack Rusin, Trolltech
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include "pixman-private.h"
|
||||
|
||||
void
|
||||
_pixman_gradient_walker_init (pixman_gradient_walker_t *walker,
|
||||
gradient_t * gradient,
|
||||
pixman_repeat_t repeat)
|
||||
{
|
||||
walker->num_stops = gradient->n_stops;
|
||||
walker->stops = gradient->stops;
|
||||
walker->left_x = 0;
|
||||
walker->right_x = 0x10000;
|
||||
walker->stepper = 0;
|
||||
walker->left_ag = 0;
|
||||
walker->left_rb = 0;
|
||||
walker->right_ag = 0;
|
||||
walker->right_rb = 0;
|
||||
walker->repeat = repeat;
|
||||
|
||||
walker->need_reset = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gradient_walker_reset (pixman_gradient_walker_t *walker,
|
||||
pixman_fixed_48_16_t pos)
|
||||
{
|
||||
int32_t x, left_x, right_x;
|
||||
pixman_color_t *left_c, *right_c;
|
||||
int n, count = walker->num_stops;
|
||||
pixman_gradient_stop_t *stops = walker->stops;
|
||||
|
||||
if (walker->repeat == PIXMAN_REPEAT_NORMAL)
|
||||
{
|
||||
x = (int32_t)pos & 0xffff;
|
||||
}
|
||||
else if (walker->repeat == PIXMAN_REPEAT_REFLECT)
|
||||
{
|
||||
x = (int32_t)pos & 0xffff;
|
||||
if ((int32_t)pos & 0x10000)
|
||||
x = 0x10000 - x;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = pos;
|
||||
}
|
||||
|
||||
for (n = 0; n < count; n++)
|
||||
{
|
||||
if (x < stops[n].x)
|
||||
break;
|
||||
}
|
||||
|
||||
left_x = stops[n - 1].x;
|
||||
left_c = &stops[n - 1].color;
|
||||
|
||||
right_x = stops[n].x;
|
||||
right_c = &stops[n].color;
|
||||
|
||||
if (walker->repeat == PIXMAN_REPEAT_NORMAL)
|
||||
{
|
||||
left_x += (pos - x);
|
||||
right_x += (pos - x);
|
||||
}
|
||||
else if (walker->repeat == PIXMAN_REPEAT_REFLECT)
|
||||
{
|
||||
if ((int32_t)pos & 0x10000)
|
||||
{
|
||||
pixman_color_t *tmp_c;
|
||||
int32_t tmp_x;
|
||||
|
||||
tmp_x = 0x10000 - right_x;
|
||||
right_x = 0x10000 - left_x;
|
||||
left_x = tmp_x;
|
||||
|
||||
tmp_c = right_c;
|
||||
right_c = left_c;
|
||||
left_c = tmp_c;
|
||||
|
||||
x = 0x10000 - x;
|
||||
}
|
||||
left_x += (pos - x);
|
||||
right_x += (pos - x);
|
||||
}
|
||||
else if (walker->repeat == PIXMAN_REPEAT_NONE)
|
||||
{
|
||||
if (n == 0)
|
||||
right_c = left_c;
|
||||
else if (n == count)
|
||||
left_c = right_c;
|
||||
}
|
||||
|
||||
walker->left_x = left_x;
|
||||
walker->right_x = right_x;
|
||||
walker->left_ag = ((left_c->alpha >> 8) << 16) | (left_c->green >> 8);
|
||||
walker->left_rb = ((left_c->red & 0xff00) << 8) | (left_c->blue >> 8);
|
||||
walker->right_ag = ((right_c->alpha >> 8) << 16) | (right_c->green >> 8);
|
||||
walker->right_rb = ((right_c->red & 0xff00) << 8) | (right_c->blue >> 8);
|
||||
|
||||
if (walker->left_x == walker->right_x ||
|
||||
(walker->left_ag == walker->right_ag &&
|
||||
walker->left_rb == walker->right_rb))
|
||||
{
|
||||
walker->stepper = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int32_t width = right_x - left_x;
|
||||
walker->stepper = ((1 << 24) + width / 2) / width;
|
||||
}
|
||||
|
||||
walker->need_reset = FALSE;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
_pixman_gradient_walker_pixel (pixman_gradient_walker_t *walker,
|
||||
pixman_fixed_48_16_t x)
|
||||
{
|
||||
int dist, idist;
|
||||
uint32_t t1, t2, a, color;
|
||||
|
||||
if (walker->need_reset || x < walker->left_x || x >= walker->right_x)
|
||||
gradient_walker_reset (walker, x);
|
||||
|
||||
dist = ((int)(x - walker->left_x) * walker->stepper) >> 16;
|
||||
idist = 256 - dist;
|
||||
|
||||
/* combined INTERPOLATE and premultiply */
|
||||
t1 = walker->left_rb * idist + walker->right_rb * dist;
|
||||
t1 = (t1 >> 8) & 0xff00ff;
|
||||
|
||||
t2 = walker->left_ag * idist + walker->right_ag * dist;
|
||||
t2 &= 0xff00ff00;
|
||||
|
||||
color = t2 & 0xff000000;
|
||||
a = t2 >> 24;
|
||||
|
||||
t1 = t1 * a + 0x800080;
|
||||
t1 = (t1 + ((t1 >> 8) & 0xff00ff)) >> 8;
|
||||
|
||||
t2 = (t2 >> 8) * a + 0x800080;
|
||||
t2 = (t2 + ((t2 >> 8) & 0xff00ff));
|
||||
|
||||
return (color | (t1 & 0xff00ff) | (t2 & 0xff00));
|
||||
}
|
||||
|
||||
967
gfx/cairo/libpixman/src/pixman-image.c
Normal file
967
gfx/cairo/libpixman/src/pixman-image.c
Normal file
|
|
@ -0,0 +1,967 @@
|
|||
/*
|
||||
* Copyright © 2000 SuSE, Inc.
|
||||
* Copyright © 2007 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of SuSE not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. SuSE makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
|
||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "pixman-private.h"
|
||||
|
||||
static const pixman_color_t transparent_black = { 0, 0, 0, 0 };
|
||||
|
||||
/**
|
||||
** bug 1293598 - clean up every pointer after free to avoid
|
||||
** "dereferencing freed memory" problem
|
||||
**/
|
||||
#define PIXMAN_POSION
|
||||
|
||||
static void
|
||||
free_memory (void** p)
|
||||
{
|
||||
#ifdef PIXMAN_POISON
|
||||
if (*p) {
|
||||
#endif
|
||||
free (*p);
|
||||
#ifdef PIXMAN_POISON
|
||||
*p = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
gradient_property_changed (pixman_image_t *image)
|
||||
{
|
||||
gradient_t *gradient = &image->gradient;
|
||||
int n = gradient->n_stops;
|
||||
pixman_gradient_stop_t *stops = gradient->stops;
|
||||
pixman_gradient_stop_t *begin = &(gradient->stops[-1]);
|
||||
pixman_gradient_stop_t *end = &(gradient->stops[n]);
|
||||
|
||||
switch (gradient->common.repeat)
|
||||
{
|
||||
default:
|
||||
case PIXMAN_REPEAT_NONE:
|
||||
begin->x = INT32_MIN;
|
||||
begin->color = transparent_black;
|
||||
end->x = INT32_MAX;
|
||||
end->color = transparent_black;
|
||||
break;
|
||||
|
||||
case PIXMAN_REPEAT_NORMAL:
|
||||
begin->x = stops[n - 1].x - pixman_fixed_1;
|
||||
begin->color = stops[n - 1].color;
|
||||
end->x = stops[0].x + pixman_fixed_1;
|
||||
end->color = stops[0].color;
|
||||
break;
|
||||
|
||||
case PIXMAN_REPEAT_REFLECT:
|
||||
begin->x = - stops[0].x;
|
||||
begin->color = stops[0].color;
|
||||
end->x = pixman_int_to_fixed (2) - stops[n - 1].x;
|
||||
end->color = stops[n - 1].color;
|
||||
break;
|
||||
|
||||
case PIXMAN_REPEAT_PAD:
|
||||
begin->x = INT32_MIN;
|
||||
begin->color = stops[0].color;
|
||||
end->x = INT32_MAX;
|
||||
end->color = stops[n - 1].color;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pixman_bool_t
|
||||
_pixman_init_gradient (gradient_t * gradient,
|
||||
const pixman_gradient_stop_t *stops,
|
||||
int n_stops)
|
||||
{
|
||||
return_val_if_fail (n_stops > 0, FALSE);
|
||||
|
||||
/* We allocate two extra stops, one before the beginning of the stop list,
|
||||
* and one after the end. These stops are initialized to whatever color
|
||||
* would be used for positions outside the range of the stop list.
|
||||
*
|
||||
* This saves a bit of computation in the gradient walker.
|
||||
*
|
||||
* The pointer we store in the gradient_t struct still points to the
|
||||
* first user-supplied struct, so when freeing, we will have to
|
||||
* subtract one.
|
||||
*/
|
||||
gradient->stops =
|
||||
pixman_malloc_ab (n_stops + 2, sizeof (pixman_gradient_stop_t));
|
||||
if (!gradient->stops)
|
||||
return FALSE;
|
||||
|
||||
gradient->stops += 1;
|
||||
memcpy (gradient->stops, stops, n_stops * sizeof (pixman_gradient_stop_t));
|
||||
gradient->n_stops = n_stops;
|
||||
|
||||
gradient->common.property_changed = gradient_property_changed;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
_pixman_image_init (pixman_image_t *image)
|
||||
{
|
||||
image_common_t *common = &image->common;
|
||||
|
||||
pixman_region32_init (&common->clip_region);
|
||||
|
||||
common->alpha_count = 0;
|
||||
common->have_clip_region = FALSE;
|
||||
common->clip_sources = FALSE;
|
||||
common->transform = NULL;
|
||||
common->repeat = PIXMAN_REPEAT_NONE;
|
||||
common->filter = PIXMAN_FILTER_NEAREST;
|
||||
common->filter_params = NULL;
|
||||
common->n_filter_params = 0;
|
||||
common->alpha_map = NULL;
|
||||
common->component_alpha = FALSE;
|
||||
common->ref_count = 1;
|
||||
common->property_changed = NULL;
|
||||
common->client_clip = FALSE;
|
||||
common->destroy_func = NULL;
|
||||
common->destroy_data = NULL;
|
||||
common->dirty = TRUE;
|
||||
}
|
||||
|
||||
pixman_bool_t
|
||||
_pixman_image_fini (pixman_image_t *image)
|
||||
{
|
||||
image_common_t *common = (image_common_t *)image;
|
||||
|
||||
common->ref_count--;
|
||||
|
||||
if (common->ref_count == 0)
|
||||
{
|
||||
if (image->common.destroy_func)
|
||||
image->common.destroy_func (image, image->common.destroy_data);
|
||||
|
||||
pixman_region32_fini (&common->clip_region);
|
||||
|
||||
free_memory (&common->transform);
|
||||
free_memory (&common->filter_params);
|
||||
|
||||
if (common->alpha_map)
|
||||
pixman_image_unref ((pixman_image_t *)common->alpha_map);
|
||||
|
||||
if (image->type == LINEAR ||
|
||||
image->type == RADIAL ||
|
||||
image->type == CONICAL)
|
||||
{
|
||||
if (image->gradient.stops)
|
||||
{
|
||||
/* See _pixman_init_gradient() for an explanation of the - 1 */
|
||||
void *addr = image->gradient.stops - 1;
|
||||
free_memory (&addr);
|
||||
}
|
||||
|
||||
/* This will trigger if someone adds a property_changed
|
||||
* method to the linear/radial/conical gradient overwriting
|
||||
* the general one.
|
||||
*/
|
||||
assert (
|
||||
image->common.property_changed == gradient_property_changed);
|
||||
}
|
||||
|
||||
if (image->type == BITS && image->bits.free_me) {
|
||||
free_memory (&image->bits.free_me);
|
||||
image->bits.bits = NULL;
|
||||
}
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pixman_image_t *
|
||||
_pixman_image_allocate (void)
|
||||
{
|
||||
pixman_image_t *image = malloc (sizeof (pixman_image_t));
|
||||
|
||||
if (image)
|
||||
_pixman_image_init (image);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
static void
|
||||
image_property_changed (pixman_image_t *image)
|
||||
{
|
||||
image->common.dirty = TRUE;
|
||||
}
|
||||
|
||||
/* Ref Counting */
|
||||
PIXMAN_EXPORT pixman_image_t *
|
||||
pixman_image_ref (pixman_image_t *image)
|
||||
{
|
||||
image->common.ref_count++;
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
/* returns TRUE when the image is freed */
|
||||
PIXMAN_EXPORT pixman_bool_t
|
||||
pixman_image_unref (pixman_image_t *image)
|
||||
{
|
||||
if (_pixman_image_fini (image))
|
||||
{
|
||||
free_memory (&image);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_image_set_destroy_function (pixman_image_t * image,
|
||||
pixman_image_destroy_func_t func,
|
||||
void * data)
|
||||
{
|
||||
image->common.destroy_func = func;
|
||||
image->common.destroy_data = data;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void *
|
||||
pixman_image_get_destroy_data (pixman_image_t *image)
|
||||
{
|
||||
return image->common.destroy_data;
|
||||
}
|
||||
|
||||
void
|
||||
_pixman_image_reset_clip_region (pixman_image_t *image)
|
||||
{
|
||||
image->common.have_clip_region = FALSE;
|
||||
}
|
||||
|
||||
/* Executive Summary: This function is a no-op that only exists
|
||||
* for historical reasons.
|
||||
*
|
||||
* There used to be a bug in the X server where it would rely on
|
||||
* out-of-bounds accesses when it was asked to composite with a
|
||||
* window as the source. It would create a pixman image pointing
|
||||
* to some bogus position in memory, but then set a clip region
|
||||
* to the position where the actual bits were.
|
||||
*
|
||||
* Due to a bug in old versions of pixman, where it would not clip
|
||||
* against the image bounds when a clip region was set, this would
|
||||
* actually work. So when the pixman bug was fixed, a workaround was
|
||||
* added to allow certain out-of-bound accesses. This function disabled
|
||||
* those workarounds.
|
||||
*
|
||||
* Since 0.21.2, pixman doesn't do these workarounds anymore, so now
|
||||
* this function is a no-op.
|
||||
*/
|
||||
PIXMAN_EXPORT void
|
||||
pixman_disable_out_of_bounds_workaround (void)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
compute_image_info (pixman_image_t *image)
|
||||
{
|
||||
pixman_format_code_t code;
|
||||
uint32_t flags = 0;
|
||||
|
||||
/* Transform */
|
||||
if (!image->common.transform)
|
||||
{
|
||||
flags |= (FAST_PATH_ID_TRANSFORM |
|
||||
FAST_PATH_X_UNIT_POSITIVE |
|
||||
FAST_PATH_Y_UNIT_ZERO |
|
||||
FAST_PATH_AFFINE_TRANSFORM);
|
||||
}
|
||||
else
|
||||
{
|
||||
flags |= FAST_PATH_HAS_TRANSFORM;
|
||||
|
||||
if (image->common.transform->matrix[2][0] == 0 &&
|
||||
image->common.transform->matrix[2][1] == 0 &&
|
||||
image->common.transform->matrix[2][2] == pixman_fixed_1)
|
||||
{
|
||||
flags |= FAST_PATH_AFFINE_TRANSFORM;
|
||||
|
||||
if (image->common.transform->matrix[0][1] == 0 &&
|
||||
image->common.transform->matrix[1][0] == 0)
|
||||
{
|
||||
if (image->common.transform->matrix[0][0] == -pixman_fixed_1 &&
|
||||
image->common.transform->matrix[1][1] == -pixman_fixed_1)
|
||||
{
|
||||
flags |= FAST_PATH_ROTATE_180_TRANSFORM;
|
||||
}
|
||||
flags |= FAST_PATH_SCALE_TRANSFORM;
|
||||
}
|
||||
else if (image->common.transform->matrix[0][0] == 0 &&
|
||||
image->common.transform->matrix[1][1] == 0)
|
||||
{
|
||||
pixman_fixed_t m01 = image->common.transform->matrix[0][1];
|
||||
pixman_fixed_t m10 = image->common.transform->matrix[1][0];
|
||||
|
||||
if (m01 == -pixman_fixed_1 && m10 == pixman_fixed_1)
|
||||
flags |= FAST_PATH_ROTATE_90_TRANSFORM;
|
||||
else if (m01 == pixman_fixed_1 && m10 == -pixman_fixed_1)
|
||||
flags |= FAST_PATH_ROTATE_270_TRANSFORM;
|
||||
}
|
||||
}
|
||||
|
||||
if (image->common.transform->matrix[0][0] > 0)
|
||||
flags |= FAST_PATH_X_UNIT_POSITIVE;
|
||||
|
||||
if (image->common.transform->matrix[1][0] == 0)
|
||||
flags |= FAST_PATH_Y_UNIT_ZERO;
|
||||
}
|
||||
|
||||
/* Filter */
|
||||
switch (image->common.filter)
|
||||
{
|
||||
case PIXMAN_FILTER_NEAREST:
|
||||
case PIXMAN_FILTER_FAST:
|
||||
flags |= (FAST_PATH_NEAREST_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
|
||||
break;
|
||||
|
||||
case PIXMAN_FILTER_BILINEAR:
|
||||
case PIXMAN_FILTER_GOOD:
|
||||
case PIXMAN_FILTER_BEST:
|
||||
flags |= (FAST_PATH_BILINEAR_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
|
||||
|
||||
/* Here we have a chance to optimize BILINEAR filter to NEAREST if
|
||||
* they are equivalent for the currently used transformation matrix.
|
||||
*/
|
||||
if (flags & FAST_PATH_ID_TRANSFORM)
|
||||
{
|
||||
flags |= FAST_PATH_NEAREST_FILTER;
|
||||
}
|
||||
else if (
|
||||
/* affine and integer translation components in matrix ... */
|
||||
((flags & FAST_PATH_AFFINE_TRANSFORM) &&
|
||||
!pixman_fixed_frac (image->common.transform->matrix[0][2] |
|
||||
image->common.transform->matrix[1][2])) &&
|
||||
(
|
||||
/* ... combined with a simple rotation */
|
||||
(flags & (FAST_PATH_ROTATE_90_TRANSFORM |
|
||||
FAST_PATH_ROTATE_180_TRANSFORM |
|
||||
FAST_PATH_ROTATE_270_TRANSFORM)) ||
|
||||
/* ... or combined with a simple non-rotated translation */
|
||||
(image->common.transform->matrix[0][0] == pixman_fixed_1 &&
|
||||
image->common.transform->matrix[1][1] == pixman_fixed_1 &&
|
||||
image->common.transform->matrix[0][1] == 0 &&
|
||||
image->common.transform->matrix[1][0] == 0)
|
||||
)
|
||||
)
|
||||
{
|
||||
/* FIXME: there are some affine-test failures, showing that
|
||||
* handling of BILINEAR and NEAREST filter is not quite
|
||||
* equivalent when getting close to 32K for the translation
|
||||
* components of the matrix. That's likely some bug, but for
|
||||
* now just skip BILINEAR->NEAREST optimization in this case.
|
||||
*/
|
||||
pixman_fixed_t magic_limit = pixman_int_to_fixed (30000);
|
||||
if (image->common.transform->matrix[0][2] <= magic_limit &&
|
||||
image->common.transform->matrix[1][2] <= magic_limit &&
|
||||
image->common.transform->matrix[0][2] >= -magic_limit &&
|
||||
image->common.transform->matrix[1][2] >= -magic_limit)
|
||||
{
|
||||
flags |= FAST_PATH_NEAREST_FILTER;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PIXMAN_FILTER_CONVOLUTION:
|
||||
break;
|
||||
|
||||
case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
|
||||
flags |= FAST_PATH_SEPARABLE_CONVOLUTION_FILTER;
|
||||
break;
|
||||
|
||||
default:
|
||||
flags |= FAST_PATH_NO_CONVOLUTION_FILTER;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Repeat mode */
|
||||
switch (image->common.repeat)
|
||||
{
|
||||
case PIXMAN_REPEAT_NONE:
|
||||
flags |=
|
||||
FAST_PATH_NO_REFLECT_REPEAT |
|
||||
FAST_PATH_NO_PAD_REPEAT |
|
||||
FAST_PATH_NO_NORMAL_REPEAT;
|
||||
break;
|
||||
|
||||
case PIXMAN_REPEAT_REFLECT:
|
||||
flags |=
|
||||
FAST_PATH_NO_PAD_REPEAT |
|
||||
FAST_PATH_NO_NONE_REPEAT |
|
||||
FAST_PATH_NO_NORMAL_REPEAT;
|
||||
break;
|
||||
|
||||
case PIXMAN_REPEAT_PAD:
|
||||
flags |=
|
||||
FAST_PATH_NO_REFLECT_REPEAT |
|
||||
FAST_PATH_NO_NONE_REPEAT |
|
||||
FAST_PATH_NO_NORMAL_REPEAT;
|
||||
break;
|
||||
|
||||
default:
|
||||
flags |=
|
||||
FAST_PATH_NO_REFLECT_REPEAT |
|
||||
FAST_PATH_NO_PAD_REPEAT |
|
||||
FAST_PATH_NO_NONE_REPEAT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Component alpha */
|
||||
if (image->common.component_alpha)
|
||||
flags |= FAST_PATH_COMPONENT_ALPHA;
|
||||
else
|
||||
flags |= FAST_PATH_UNIFIED_ALPHA;
|
||||
|
||||
flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NARROW_FORMAT);
|
||||
|
||||
/* Type specific checks */
|
||||
switch (image->type)
|
||||
{
|
||||
case SOLID:
|
||||
code = PIXMAN_solid;
|
||||
|
||||
if (image->solid.color.alpha == 0xffff)
|
||||
flags |= FAST_PATH_IS_OPAQUE;
|
||||
break;
|
||||
|
||||
case BITS:
|
||||
if (image->bits.width == 1 &&
|
||||
image->bits.height == 1 &&
|
||||
image->common.repeat != PIXMAN_REPEAT_NONE)
|
||||
{
|
||||
code = PIXMAN_solid;
|
||||
}
|
||||
else
|
||||
{
|
||||
code = image->bits.format;
|
||||
flags |= FAST_PATH_BITS_IMAGE;
|
||||
}
|
||||
|
||||
if (!PIXMAN_FORMAT_A (image->bits.format) &&
|
||||
PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_GRAY &&
|
||||
PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_COLOR)
|
||||
{
|
||||
flags |= FAST_PATH_SAMPLES_OPAQUE;
|
||||
|
||||
if (image->common.repeat != PIXMAN_REPEAT_NONE)
|
||||
flags |= FAST_PATH_IS_OPAQUE;
|
||||
}
|
||||
|
||||
if (image->bits.read_func || image->bits.write_func)
|
||||
flags &= ~FAST_PATH_NO_ACCESSORS;
|
||||
|
||||
if (PIXMAN_FORMAT_IS_WIDE (image->bits.format))
|
||||
flags &= ~FAST_PATH_NARROW_FORMAT;
|
||||
|
||||
if (image->bits.format == PIXMAN_r5g6b5)
|
||||
flags |= FAST_PATH_16_FORMAT;
|
||||
|
||||
break;
|
||||
|
||||
case RADIAL:
|
||||
code = PIXMAN_unknown;
|
||||
|
||||
/*
|
||||
* As explained in pixman-radial-gradient.c, every point of
|
||||
* the plane has a valid associated radius (and thus will be
|
||||
* colored) if and only if a is negative (i.e. one of the two
|
||||
* circles contains the other one).
|
||||
*/
|
||||
|
||||
if (image->radial.a >= 0)
|
||||
break;
|
||||
|
||||
/* Fall through */
|
||||
|
||||
case CONICAL:
|
||||
case LINEAR:
|
||||
code = PIXMAN_unknown;
|
||||
|
||||
if (image->common.repeat != PIXMAN_REPEAT_NONE)
|
||||
{
|
||||
int i;
|
||||
|
||||
flags |= FAST_PATH_IS_OPAQUE;
|
||||
for (i = 0; i < image->gradient.n_stops; ++i)
|
||||
{
|
||||
if (image->gradient.stops[i].color.alpha != 0xffff)
|
||||
{
|
||||
flags &= ~FAST_PATH_IS_OPAQUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
code = PIXMAN_unknown;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Alpha map */
|
||||
if (!image->common.alpha_map)
|
||||
{
|
||||
flags |= FAST_PATH_NO_ALPHA_MAP;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PIXMAN_FORMAT_IS_WIDE (image->common.alpha_map->format))
|
||||
flags &= ~FAST_PATH_NARROW_FORMAT;
|
||||
}
|
||||
|
||||
/* Both alpha maps and convolution filters can introduce
|
||||
* non-opaqueness in otherwise opaque images. Also
|
||||
* an image with component alpha turned on is only opaque
|
||||
* if all channels are opaque, so we simply turn it off
|
||||
* unconditionally for those images.
|
||||
*/
|
||||
if (image->common.alpha_map ||
|
||||
image->common.filter == PIXMAN_FILTER_CONVOLUTION ||
|
||||
image->common.filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION ||
|
||||
image->common.component_alpha)
|
||||
{
|
||||
flags &= ~(FAST_PATH_IS_OPAQUE | FAST_PATH_SAMPLES_OPAQUE);
|
||||
}
|
||||
|
||||
image->common.flags = flags;
|
||||
image->common.extended_format_code = code;
|
||||
}
|
||||
|
||||
void
|
||||
_pixman_image_validate (pixman_image_t *image)
|
||||
{
|
||||
if (image->common.dirty)
|
||||
{
|
||||
compute_image_info (image);
|
||||
|
||||
/* It is important that property_changed is
|
||||
* called *after* compute_image_info() because
|
||||
* property_changed() can make use of the flags
|
||||
* to set up accessors etc.
|
||||
*/
|
||||
if (image->common.property_changed)
|
||||
image->common.property_changed (image);
|
||||
|
||||
image->common.dirty = FALSE;
|
||||
}
|
||||
|
||||
if (image->common.alpha_map)
|
||||
_pixman_image_validate ((pixman_image_t *)image->common.alpha_map);
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT pixman_bool_t
|
||||
pixman_image_set_clip_region32 (pixman_image_t * image,
|
||||
pixman_region32_t *region)
|
||||
{
|
||||
image_common_t *common = (image_common_t *)image;
|
||||
pixman_bool_t result;
|
||||
|
||||
if (region)
|
||||
{
|
||||
if ((result = pixman_region32_copy (&common->clip_region, region)))
|
||||
image->common.have_clip_region = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
_pixman_image_reset_clip_region (image);
|
||||
|
||||
result = TRUE;
|
||||
}
|
||||
|
||||
image_property_changed (image);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT pixman_bool_t
|
||||
pixman_image_set_clip_region (pixman_image_t * image,
|
||||
pixman_region16_t *region)
|
||||
{
|
||||
image_common_t *common = (image_common_t *)image;
|
||||
pixman_bool_t result;
|
||||
|
||||
if (region)
|
||||
{
|
||||
if ((result = pixman_region32_copy_from_region16 (&common->clip_region, region)))
|
||||
image->common.have_clip_region = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
_pixman_image_reset_clip_region (image);
|
||||
|
||||
result = TRUE;
|
||||
}
|
||||
|
||||
image_property_changed (image);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_image_set_has_client_clip (pixman_image_t *image,
|
||||
pixman_bool_t client_clip)
|
||||
{
|
||||
image->common.client_clip = client_clip;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT pixman_bool_t
|
||||
pixman_image_set_transform (pixman_image_t * image,
|
||||
const pixman_transform_t *transform)
|
||||
{
|
||||
static const pixman_transform_t id =
|
||||
{
|
||||
{ { pixman_fixed_1, 0, 0 },
|
||||
{ 0, pixman_fixed_1, 0 },
|
||||
{ 0, 0, pixman_fixed_1 } }
|
||||
};
|
||||
|
||||
image_common_t *common = (image_common_t *)image;
|
||||
pixman_bool_t result;
|
||||
|
||||
if (common->transform == transform)
|
||||
return TRUE;
|
||||
|
||||
if (!transform || memcmp (&id, transform, sizeof (pixman_transform_t)) == 0)
|
||||
{
|
||||
free (common->transform);
|
||||
common->transform = NULL;
|
||||
result = TRUE;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (common->transform &&
|
||||
memcmp (common->transform, transform, sizeof (pixman_transform_t)) == 0)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (common->transform == NULL)
|
||||
common->transform = malloc (sizeof (pixman_transform_t));
|
||||
|
||||
if (common->transform == NULL)
|
||||
{
|
||||
result = FALSE;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy (common->transform, transform, sizeof(pixman_transform_t));
|
||||
|
||||
result = TRUE;
|
||||
|
||||
out:
|
||||
image_property_changed (image);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_image_set_repeat (pixman_image_t *image,
|
||||
pixman_repeat_t repeat)
|
||||
{
|
||||
if (image->common.repeat == repeat)
|
||||
return;
|
||||
|
||||
image->common.repeat = repeat;
|
||||
|
||||
image_property_changed (image);
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT pixman_bool_t
|
||||
pixman_image_set_filter (pixman_image_t * image,
|
||||
pixman_filter_t filter,
|
||||
const pixman_fixed_t *params,
|
||||
int n_params)
|
||||
{
|
||||
image_common_t *common = (image_common_t *)image;
|
||||
pixman_fixed_t *new_params;
|
||||
|
||||
if (params == common->filter_params && filter == common->filter)
|
||||
return TRUE;
|
||||
|
||||
if (filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION)
|
||||
{
|
||||
int width = pixman_fixed_to_int (params[0]);
|
||||
int height = pixman_fixed_to_int (params[1]);
|
||||
int x_phase_bits = pixman_fixed_to_int (params[2]);
|
||||
int y_phase_bits = pixman_fixed_to_int (params[3]);
|
||||
int n_x_phases = (1 << x_phase_bits);
|
||||
int n_y_phases = (1 << y_phase_bits);
|
||||
|
||||
return_val_if_fail (
|
||||
n_params == 4 + n_x_phases * width + n_y_phases * height, FALSE);
|
||||
}
|
||||
|
||||
new_params = NULL;
|
||||
if (params)
|
||||
{
|
||||
new_params = pixman_malloc_ab (n_params, sizeof (pixman_fixed_t));
|
||||
if (!new_params)
|
||||
return FALSE;
|
||||
|
||||
memcpy (new_params,
|
||||
params, n_params * sizeof (pixman_fixed_t));
|
||||
}
|
||||
|
||||
common->filter = filter;
|
||||
|
||||
if (common->filter_params)
|
||||
free (common->filter_params);
|
||||
|
||||
common->filter_params = new_params;
|
||||
common->n_filter_params = n_params;
|
||||
|
||||
image_property_changed (image);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_image_set_source_clipping (pixman_image_t *image,
|
||||
pixman_bool_t clip_sources)
|
||||
{
|
||||
if (image->common.clip_sources == clip_sources)
|
||||
return;
|
||||
|
||||
image->common.clip_sources = clip_sources;
|
||||
|
||||
image_property_changed (image);
|
||||
}
|
||||
|
||||
/* Unlike all the other property setters, this function does not
|
||||
* copy the content of indexed. Doing this copying is simply
|
||||
* way, way too expensive.
|
||||
*/
|
||||
PIXMAN_EXPORT void
|
||||
pixman_image_set_indexed (pixman_image_t * image,
|
||||
const pixman_indexed_t *indexed)
|
||||
{
|
||||
bits_image_t *bits = (bits_image_t *)image;
|
||||
|
||||
if (bits->indexed == indexed)
|
||||
return;
|
||||
|
||||
bits->indexed = indexed;
|
||||
|
||||
image_property_changed (image);
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_image_set_alpha_map (pixman_image_t *image,
|
||||
pixman_image_t *alpha_map,
|
||||
int16_t x,
|
||||
int16_t y)
|
||||
{
|
||||
image_common_t *common = (image_common_t *)image;
|
||||
|
||||
return_if_fail (!alpha_map || alpha_map->type == BITS);
|
||||
|
||||
if (alpha_map && common->alpha_count > 0)
|
||||
{
|
||||
/* If this image is being used as an alpha map itself,
|
||||
* then you can't give it an alpha map of its own.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
if (alpha_map && alpha_map->common.alpha_map)
|
||||
{
|
||||
/* If the image has an alpha map of its own,
|
||||
* then it can't be used as an alpha map itself
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
if (common->alpha_map != (bits_image_t *)alpha_map)
|
||||
{
|
||||
if (common->alpha_map)
|
||||
{
|
||||
common->alpha_map->common.alpha_count--;
|
||||
|
||||
pixman_image_unref ((pixman_image_t *)common->alpha_map);
|
||||
}
|
||||
|
||||
if (alpha_map)
|
||||
{
|
||||
common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map);
|
||||
|
||||
common->alpha_map->common.alpha_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
common->alpha_map = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
common->alpha_origin_x = x;
|
||||
common->alpha_origin_y = y;
|
||||
|
||||
image_property_changed (image);
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_image_set_component_alpha (pixman_image_t *image,
|
||||
pixman_bool_t component_alpha)
|
||||
{
|
||||
if (image->common.component_alpha == component_alpha)
|
||||
return;
|
||||
|
||||
image->common.component_alpha = component_alpha;
|
||||
|
||||
image_property_changed (image);
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT pixman_bool_t
|
||||
pixman_image_get_component_alpha (pixman_image_t *image)
|
||||
{
|
||||
return image->common.component_alpha;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_image_set_accessors (pixman_image_t * image,
|
||||
pixman_read_memory_func_t read_func,
|
||||
pixman_write_memory_func_t write_func)
|
||||
{
|
||||
return_if_fail (image != NULL);
|
||||
|
||||
if (image->type == BITS)
|
||||
{
|
||||
image->bits.read_func = read_func;
|
||||
image->bits.write_func = write_func;
|
||||
|
||||
image_property_changed (image);
|
||||
}
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT uint32_t *
|
||||
pixman_image_get_data (pixman_image_t *image)
|
||||
{
|
||||
if (image->type == BITS)
|
||||
return image->bits.bits;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT int
|
||||
pixman_image_get_width (pixman_image_t *image)
|
||||
{
|
||||
if (image->type == BITS)
|
||||
return image->bits.width;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT int
|
||||
pixman_image_get_height (pixman_image_t *image)
|
||||
{
|
||||
if (image->type == BITS)
|
||||
return image->bits.height;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT int
|
||||
pixman_image_get_stride (pixman_image_t *image)
|
||||
{
|
||||
if (image->type == BITS)
|
||||
return image->bits.rowstride * (int) sizeof (uint32_t);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT int
|
||||
pixman_image_get_depth (pixman_image_t *image)
|
||||
{
|
||||
if (image->type == BITS)
|
||||
return PIXMAN_FORMAT_DEPTH (image->bits.format);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT pixman_format_code_t
|
||||
pixman_image_get_format (pixman_image_t *image)
|
||||
{
|
||||
if (image->type == BITS)
|
||||
return image->bits.format;
|
||||
|
||||
return PIXMAN_null;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
_pixman_image_get_solid (pixman_implementation_t *imp,
|
||||
pixman_image_t * image,
|
||||
pixman_format_code_t format)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
if (image->type == SOLID)
|
||||
{
|
||||
result = image->solid.color_32;
|
||||
}
|
||||
else if (image->type == BITS)
|
||||
{
|
||||
if (image->bits.format == PIXMAN_a8r8g8b8)
|
||||
result = image->bits.bits[0];
|
||||
else if (image->bits.format == PIXMAN_x8r8g8b8)
|
||||
result = image->bits.bits[0] | 0xff000000;
|
||||
else if (image->bits.format == PIXMAN_a8)
|
||||
result = (*(uint8_t *)image->bits.bits) << 24;
|
||||
else
|
||||
goto otherwise;
|
||||
}
|
||||
else
|
||||
{
|
||||
pixman_iter_t iter;
|
||||
|
||||
otherwise:
|
||||
_pixman_implementation_src_iter_init (
|
||||
imp, &iter, image, 0, 0, 1, 1,
|
||||
(uint8_t *)&result,
|
||||
ITER_NARROW, image->common.flags);
|
||||
|
||||
result = *iter.get_scanline (&iter, NULL);
|
||||
}
|
||||
|
||||
/* If necessary, convert RGB <--> BGR. */
|
||||
if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB
|
||||
&& PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB_SRGB)
|
||||
{
|
||||
result = (((result & 0xff000000) >> 0) |
|
||||
((result & 0x00ff0000) >> 16) |
|
||||
((result & 0x0000ff00) >> 0) |
|
||||
((result & 0x000000ff) << 16));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
405
gfx/cairo/libpixman/src/pixman-implementation.c
Normal file
405
gfx/cairo/libpixman/src/pixman-implementation.c
Normal file
|
|
@ -0,0 +1,405 @@
|
|||
/*
|
||||
* Copyright © 2009 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Red Hat not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. Red Hat makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include "pixman-private.h"
|
||||
|
||||
pixman_implementation_t *
|
||||
_pixman_implementation_create (pixman_implementation_t *fallback,
|
||||
const pixman_fast_path_t *fast_paths)
|
||||
{
|
||||
pixman_implementation_t *imp;
|
||||
|
||||
assert (fast_paths);
|
||||
|
||||
if ((imp = malloc (sizeof (pixman_implementation_t))))
|
||||
{
|
||||
pixman_implementation_t *d;
|
||||
|
||||
memset (imp, 0, sizeof *imp);
|
||||
|
||||
imp->fallback = fallback;
|
||||
imp->fast_paths = fast_paths;
|
||||
|
||||
/* Make sure the whole fallback chain has the right toplevel */
|
||||
for (d = imp; d != NULL; d = d->fallback)
|
||||
d->toplevel = imp;
|
||||
}
|
||||
|
||||
return imp;
|
||||
}
|
||||
|
||||
#define N_CACHED_FAST_PATHS 8
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
pixman_implementation_t * imp;
|
||||
pixman_fast_path_t fast_path;
|
||||
} cache [N_CACHED_FAST_PATHS];
|
||||
} cache_t;
|
||||
|
||||
PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache);
|
||||
|
||||
static void
|
||||
dummy_composite_rect (pixman_implementation_t *imp,
|
||||
pixman_composite_info_t *info)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
_pixman_implementation_lookup_composite (pixman_implementation_t *toplevel,
|
||||
pixman_op_t op,
|
||||
pixman_format_code_t src_format,
|
||||
uint32_t src_flags,
|
||||
pixman_format_code_t mask_format,
|
||||
uint32_t mask_flags,
|
||||
pixman_format_code_t dest_format,
|
||||
uint32_t dest_flags,
|
||||
pixman_implementation_t **out_imp,
|
||||
pixman_composite_func_t *out_func)
|
||||
{
|
||||
pixman_implementation_t *imp;
|
||||
cache_t *cache;
|
||||
int i;
|
||||
|
||||
/* Check cache for fast paths */
|
||||
cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache);
|
||||
|
||||
/* Bug 1324130 - For compatibility with Windows XP, we have to use Tls
|
||||
* functions for the per-thread fast-path cache instead of the safer
|
||||
* __declspec(thread) mechanism. If the Tls functions fail to set up
|
||||
* the storage for some reason, cache will end up null here. As a
|
||||
* temporary workaround, just check that cache is not null before
|
||||
* using it. The implementation lookup will still function without the
|
||||
* fast-path cache, however, it will incur a slow linear search.
|
||||
*/
|
||||
if (cache) for (i = 0; i < N_CACHED_FAST_PATHS; ++i)
|
||||
{
|
||||
const pixman_fast_path_t *info = &(cache->cache[i].fast_path);
|
||||
|
||||
/* Note that we check for equality here, not whether
|
||||
* the cached fast path matches. This is to prevent
|
||||
* us from selecting an overly general fast path
|
||||
* when a more specific one would work.
|
||||
*/
|
||||
if (info->op == op &&
|
||||
info->src_format == src_format &&
|
||||
info->mask_format == mask_format &&
|
||||
info->dest_format == dest_format &&
|
||||
info->src_flags == src_flags &&
|
||||
info->mask_flags == mask_flags &&
|
||||
info->dest_flags == dest_flags &&
|
||||
info->func)
|
||||
{
|
||||
*out_imp = cache->cache[i].imp;
|
||||
*out_func = cache->cache[i].fast_path.func;
|
||||
|
||||
goto update_cache;
|
||||
}
|
||||
}
|
||||
|
||||
for (imp = toplevel; imp != NULL; imp = imp->fallback)
|
||||
{
|
||||
const pixman_fast_path_t *info = imp->fast_paths;
|
||||
|
||||
while (info->op != PIXMAN_OP_NONE)
|
||||
{
|
||||
if ((info->op == op || info->op == PIXMAN_OP_any) &&
|
||||
/* Formats */
|
||||
((info->src_format == src_format) ||
|
||||
(info->src_format == PIXMAN_any)) &&
|
||||
((info->mask_format == mask_format) ||
|
||||
(info->mask_format == PIXMAN_any)) &&
|
||||
((info->dest_format == dest_format) ||
|
||||
(info->dest_format == PIXMAN_any)) &&
|
||||
/* Flags */
|
||||
(info->src_flags & src_flags) == info->src_flags &&
|
||||
(info->mask_flags & mask_flags) == info->mask_flags &&
|
||||
(info->dest_flags & dest_flags) == info->dest_flags)
|
||||
{
|
||||
*out_imp = imp;
|
||||
*out_func = info->func;
|
||||
|
||||
/* Set i to the last spot in the cache so that the
|
||||
* move-to-front code below will work
|
||||
*/
|
||||
i = N_CACHED_FAST_PATHS - 1;
|
||||
|
||||
goto update_cache;
|
||||
}
|
||||
|
||||
++info;
|
||||
}
|
||||
}
|
||||
|
||||
/* We should never reach this point */
|
||||
_pixman_log_error (FUNC, "No known composite function\n");
|
||||
*out_imp = NULL;
|
||||
*out_func = dummy_composite_rect;
|
||||
|
||||
update_cache:
|
||||
if (cache && i)
|
||||
{
|
||||
while (i--)
|
||||
cache->cache[i + 1] = cache->cache[i];
|
||||
|
||||
cache->cache[0].imp = *out_imp;
|
||||
cache->cache[0].fast_path.op = op;
|
||||
cache->cache[0].fast_path.src_format = src_format;
|
||||
cache->cache[0].fast_path.src_flags = src_flags;
|
||||
cache->cache[0].fast_path.mask_format = mask_format;
|
||||
cache->cache[0].fast_path.mask_flags = mask_flags;
|
||||
cache->cache[0].fast_path.dest_format = dest_format;
|
||||
cache->cache[0].fast_path.dest_flags = dest_flags;
|
||||
cache->cache[0].fast_path.func = *out_func;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dummy_combine (pixman_implementation_t *imp,
|
||||
pixman_op_t op,
|
||||
uint32_t * pd,
|
||||
const uint32_t * ps,
|
||||
const uint32_t * pm,
|
||||
int w)
|
||||
{
|
||||
}
|
||||
|
||||
pixman_combine_32_func_t
|
||||
_pixman_implementation_lookup_combiner (pixman_implementation_t *imp,
|
||||
pixman_op_t op,
|
||||
pixman_bool_t component_alpha,
|
||||
pixman_bool_t narrow,
|
||||
pixman_bool_t rgb16)
|
||||
{
|
||||
while (imp)
|
||||
{
|
||||
pixman_combine_32_func_t f = NULL;
|
||||
|
||||
switch ((narrow << 1) | component_alpha)
|
||||
{
|
||||
case 0: /* not narrow, not component alpha */
|
||||
f = (pixman_combine_32_func_t)imp->combine_float[op];
|
||||
break;
|
||||
|
||||
case 1: /* not narrow, component_alpha */
|
||||
f = (pixman_combine_32_func_t)imp->combine_float_ca[op];
|
||||
break;
|
||||
|
||||
case 2: /* narrow, not component alpha */
|
||||
f = imp->combine_32[op];
|
||||
break;
|
||||
|
||||
case 3: /* narrow, component_alpha */
|
||||
f = imp->combine_32_ca[op];
|
||||
break;
|
||||
}
|
||||
if (rgb16)
|
||||
f = (pixman_combine_32_func_t *)imp->combine_16[op];
|
||||
|
||||
if (f)
|
||||
return f;
|
||||
|
||||
imp = imp->fallback;
|
||||
}
|
||||
|
||||
/* We should never reach this point */
|
||||
_pixman_log_error (FUNC, "No known combine function\n");
|
||||
return dummy_combine;
|
||||
}
|
||||
|
||||
pixman_bool_t
|
||||
_pixman_implementation_blt (pixman_implementation_t * imp,
|
||||
uint32_t * src_bits,
|
||||
uint32_t * dst_bits,
|
||||
int src_stride,
|
||||
int dst_stride,
|
||||
int src_bpp,
|
||||
int dst_bpp,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dest_x,
|
||||
int dest_y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
while (imp)
|
||||
{
|
||||
if (imp->blt &&
|
||||
(*imp->blt) (imp, src_bits, dst_bits, src_stride, dst_stride,
|
||||
src_bpp, dst_bpp, src_x, src_y, dest_x, dest_y,
|
||||
width, height))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
imp = imp->fallback;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pixman_bool_t
|
||||
_pixman_implementation_fill (pixman_implementation_t *imp,
|
||||
uint32_t * bits,
|
||||
int stride,
|
||||
int bpp,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
uint32_t filler)
|
||||
{
|
||||
while (imp)
|
||||
{
|
||||
if (imp->fill &&
|
||||
((*imp->fill) (imp, bits, stride, bpp, x, y, width, height, filler)))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
imp = imp->fallback;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pixman_bool_t
|
||||
_pixman_implementation_src_iter_init (pixman_implementation_t *imp,
|
||||
pixman_iter_t *iter,
|
||||
pixman_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
uint8_t *buffer,
|
||||
iter_flags_t iter_flags,
|
||||
uint32_t image_flags)
|
||||
{
|
||||
iter->image = image;
|
||||
iter->buffer = (uint32_t *)buffer;
|
||||
iter->x = x;
|
||||
iter->y = y;
|
||||
iter->width = width;
|
||||
iter->height = height;
|
||||
iter->iter_flags = iter_flags;
|
||||
iter->image_flags = image_flags;
|
||||
|
||||
while (imp)
|
||||
{
|
||||
if (imp->src_iter_init && (*imp->src_iter_init) (imp, iter))
|
||||
return TRUE;
|
||||
|
||||
imp = imp->fallback;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pixman_bool_t
|
||||
_pixman_implementation_dest_iter_init (pixman_implementation_t *imp,
|
||||
pixman_iter_t *iter,
|
||||
pixman_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
uint8_t *buffer,
|
||||
iter_flags_t iter_flags,
|
||||
uint32_t image_flags)
|
||||
{
|
||||
iter->image = image;
|
||||
iter->buffer = (uint32_t *)buffer;
|
||||
iter->x = x;
|
||||
iter->y = y;
|
||||
iter->width = width;
|
||||
iter->height = height;
|
||||
iter->iter_flags = iter_flags;
|
||||
iter->image_flags = image_flags;
|
||||
|
||||
while (imp)
|
||||
{
|
||||
if (imp->dest_iter_init && (*imp->dest_iter_init) (imp, iter))
|
||||
return TRUE;
|
||||
|
||||
imp = imp->fallback;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pixman_bool_t
|
||||
_pixman_disabled (const char *name)
|
||||
{
|
||||
const char *env;
|
||||
|
||||
if ((env = getenv ("PIXMAN_DISABLE")))
|
||||
{
|
||||
do
|
||||
{
|
||||
const char *end;
|
||||
int len;
|
||||
|
||||
if ((end = strchr (env, ' ')))
|
||||
len = end - env;
|
||||
else
|
||||
len = strlen (env);
|
||||
|
||||
if (strlen (name) == len && strncmp (name, env, len) == 0)
|
||||
{
|
||||
printf ("pixman: Disabled %s implementation\n", name);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
env += len;
|
||||
}
|
||||
while (*env++);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pixman_implementation_t *
|
||||
_pixman_choose_implementation (void)
|
||||
{
|
||||
pixman_implementation_t *imp;
|
||||
|
||||
imp = _pixman_implementation_create_general();
|
||||
|
||||
if (!_pixman_disabled ("fast"))
|
||||
imp = _pixman_implementation_create_fast_path (imp);
|
||||
|
||||
imp = _pixman_x86_get_implementations (imp);
|
||||
imp = _pixman_arm_get_implementations (imp);
|
||||
imp = _pixman_ppc_get_implementations (imp);
|
||||
imp = _pixman_mips_get_implementations (imp);
|
||||
|
||||
imp = _pixman_implementation_create_noop (imp);
|
||||
|
||||
return imp;
|
||||
}
|
||||
1421
gfx/cairo/libpixman/src/pixman-inlines.h
Normal file
1421
gfx/cairo/libpixman/src/pixman-inlines.h
Normal file
File diff suppressed because it is too large
Load diff
444
gfx/cairo/libpixman/src/pixman-linear-gradient.c
Normal file
444
gfx/cairo/libpixman/src/pixman-linear-gradient.c
Normal file
|
|
@ -0,0 +1,444 @@
|
|||
/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
|
||||
/*
|
||||
* Copyright © 2000 SuSE, Inc.
|
||||
* Copyright © 2007 Red Hat, Inc.
|
||||
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
|
||||
* 2005 Lars Knoll & Zack Rusin, Trolltech
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include "pixman-private.h"
|
||||
|
||||
#include "pixman-dither.h"
|
||||
|
||||
static pixman_bool_t
|
||||
linear_gradient_is_horizontal (pixman_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
linear_gradient_t *linear = (linear_gradient_t *)image;
|
||||
pixman_vector_t v;
|
||||
pixman_fixed_32_32_t l;
|
||||
pixman_fixed_48_16_t dx, dy;
|
||||
double inc;
|
||||
|
||||
if (image->common.transform)
|
||||
{
|
||||
/* projective transformation */
|
||||
if (image->common.transform->matrix[2][0] != 0 ||
|
||||
image->common.transform->matrix[2][1] != 0 ||
|
||||
image->common.transform->matrix[2][2] == 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
v.vector[0] = image->common.transform->matrix[0][1];
|
||||
v.vector[1] = image->common.transform->matrix[1][1];
|
||||
v.vector[2] = image->common.transform->matrix[2][2];
|
||||
}
|
||||
else
|
||||
{
|
||||
v.vector[0] = 0;
|
||||
v.vector[1] = pixman_fixed_1;
|
||||
v.vector[2] = pixman_fixed_1;
|
||||
}
|
||||
|
||||
dx = linear->p2.x - linear->p1.x;
|
||||
dy = linear->p2.y - linear->p1.y;
|
||||
|
||||
l = dx * dx + dy * dy;
|
||||
|
||||
if (l == 0)
|
||||
return FALSE;
|
||||
|
||||
/*
|
||||
* compute how much the input of the gradient walked changes
|
||||
* when moving vertically through the whole image
|
||||
*/
|
||||
inc = height * (double) pixman_fixed_1 * pixman_fixed_1 *
|
||||
(dx * v.vector[0] + dy * v.vector[1]) /
|
||||
(v.vector[2] * (double) l);
|
||||
|
||||
/* check that casting to integer would result in 0 */
|
||||
if (-1 < inc && inc < 1)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static uint32_t *
|
||||
linear_get_scanline_narrow (pixman_iter_t *iter,
|
||||
const uint32_t *mask)
|
||||
{
|
||||
pixman_image_t *image = iter->image;
|
||||
int x = iter->x;
|
||||
int y = iter->y;
|
||||
int width = iter->width;
|
||||
uint32_t * buffer = iter->buffer;
|
||||
|
||||
pixman_vector_t v, unit;
|
||||
pixman_fixed_32_32_t l;
|
||||
pixman_fixed_48_16_t dx, dy;
|
||||
gradient_t *gradient = (gradient_t *)image;
|
||||
linear_gradient_t *linear = (linear_gradient_t *)image;
|
||||
uint32_t *end = buffer + width;
|
||||
pixman_gradient_walker_t walker;
|
||||
|
||||
_pixman_gradient_walker_init (&walker, gradient, image->common.repeat);
|
||||
|
||||
/* reference point is the center of the pixel */
|
||||
v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2;
|
||||
v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2;
|
||||
v.vector[2] = pixman_fixed_1;
|
||||
|
||||
if (image->common.transform)
|
||||
{
|
||||
if (!pixman_transform_point_3d (image->common.transform, &v))
|
||||
return iter->buffer;
|
||||
|
||||
unit.vector[0] = image->common.transform->matrix[0][0];
|
||||
unit.vector[1] = image->common.transform->matrix[1][0];
|
||||
unit.vector[2] = image->common.transform->matrix[2][0];
|
||||
}
|
||||
else
|
||||
{
|
||||
unit.vector[0] = pixman_fixed_1;
|
||||
unit.vector[1] = 0;
|
||||
unit.vector[2] = 0;
|
||||
}
|
||||
|
||||
dx = linear->p2.x - linear->p1.x;
|
||||
dy = linear->p2.y - linear->p1.y;
|
||||
|
||||
l = dx * dx + dy * dy;
|
||||
|
||||
if (l == 0 || unit.vector[2] == 0)
|
||||
{
|
||||
/* affine transformation only */
|
||||
pixman_fixed_32_32_t t, next_inc;
|
||||
double inc;
|
||||
|
||||
if (l == 0 || v.vector[2] == 0)
|
||||
{
|
||||
t = 0;
|
||||
inc = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
double invden, v2;
|
||||
|
||||
invden = pixman_fixed_1 * (double) pixman_fixed_1 /
|
||||
(l * (double) v.vector[2]);
|
||||
v2 = v.vector[2] * (1. / pixman_fixed_1);
|
||||
t = ((dx * v.vector[0] + dy * v.vector[1]) -
|
||||
(dx * linear->p1.x + dy * linear->p1.y) * v2) * invden;
|
||||
inc = (dx * unit.vector[0] + dy * unit.vector[1]) * invden;
|
||||
}
|
||||
next_inc = 0;
|
||||
|
||||
if (((pixman_fixed_32_32_t )(inc * width)) == 0)
|
||||
{
|
||||
register uint32_t color;
|
||||
|
||||
color = _pixman_gradient_walker_pixel (&walker, t);
|
||||
while (buffer < end)
|
||||
*buffer++ = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
while (buffer < end)
|
||||
{
|
||||
if (!mask || *mask++)
|
||||
{
|
||||
*buffer = _pixman_gradient_walker_pixel (&walker,
|
||||
t + next_inc);
|
||||
}
|
||||
i++;
|
||||
next_inc = inc * i;
|
||||
buffer++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* projective transformation */
|
||||
double t;
|
||||
|
||||
t = 0;
|
||||
|
||||
while (buffer < end)
|
||||
{
|
||||
if (!mask || *mask++)
|
||||
{
|
||||
if (v.vector[2] != 0)
|
||||
{
|
||||
double invden, v2;
|
||||
|
||||
invden = pixman_fixed_1 * (double) pixman_fixed_1 /
|
||||
(l * (double) v.vector[2]);
|
||||
v2 = v.vector[2] * (1. / pixman_fixed_1);
|
||||
t = ((dx * v.vector[0] + dy * v.vector[1]) -
|
||||
(dx * linear->p1.x + dy * linear->p1.y) * v2) * invden;
|
||||
}
|
||||
|
||||
*buffer = _pixman_gradient_walker_pixel (&walker, t);
|
||||
}
|
||||
|
||||
++buffer;
|
||||
|
||||
v.vector[0] += unit.vector[0];
|
||||
v.vector[1] += unit.vector[1];
|
||||
v.vector[2] += unit.vector[2];
|
||||
}
|
||||
}
|
||||
|
||||
iter->y++;
|
||||
|
||||
return iter->buffer;
|
||||
}
|
||||
|
||||
static uint32_t *
|
||||
linear_get_scanline_16 (pixman_iter_t *iter,
|
||||
const uint32_t *mask)
|
||||
{
|
||||
pixman_image_t *image = iter->image;
|
||||
int x = iter->x;
|
||||
int y = iter->y;
|
||||
int width = iter->width;
|
||||
uint16_t * buffer = (uint16_t*)iter->buffer;
|
||||
pixman_bool_t toggle = ((x ^ y) & 1);
|
||||
|
||||
pixman_vector_t v, unit;
|
||||
pixman_fixed_32_32_t l;
|
||||
pixman_fixed_48_16_t dx, dy;
|
||||
gradient_t *gradient = (gradient_t *)image;
|
||||
linear_gradient_t *linear = (linear_gradient_t *)image;
|
||||
uint16_t *end = buffer + width;
|
||||
pixman_gradient_walker_t walker;
|
||||
|
||||
_pixman_gradient_walker_init (&walker, gradient, image->common.repeat);
|
||||
|
||||
/* reference point is the center of the pixel */
|
||||
v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2;
|
||||
v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2;
|
||||
v.vector[2] = pixman_fixed_1;
|
||||
|
||||
if (image->common.transform)
|
||||
{
|
||||
if (!pixman_transform_point_3d (image->common.transform, &v))
|
||||
return iter->buffer;
|
||||
|
||||
unit.vector[0] = image->common.transform->matrix[0][0];
|
||||
unit.vector[1] = image->common.transform->matrix[1][0];
|
||||
unit.vector[2] = image->common.transform->matrix[2][0];
|
||||
}
|
||||
else
|
||||
{
|
||||
unit.vector[0] = pixman_fixed_1;
|
||||
unit.vector[1] = 0;
|
||||
unit.vector[2] = 0;
|
||||
}
|
||||
|
||||
dx = linear->p2.x - linear->p1.x;
|
||||
dy = linear->p2.y - linear->p1.y;
|
||||
|
||||
l = dx * dx + dy * dy;
|
||||
|
||||
if (l == 0 || unit.vector[2] == 0)
|
||||
{
|
||||
/* affine transformation only */
|
||||
pixman_fixed_32_32_t t, next_inc;
|
||||
double inc;
|
||||
|
||||
if (l == 0 || v.vector[2] == 0)
|
||||
{
|
||||
t = 0;
|
||||
inc = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
double invden, v2;
|
||||
|
||||
invden = pixman_fixed_1 * (double) pixman_fixed_1 /
|
||||
(l * (double) v.vector[2]);
|
||||
v2 = v.vector[2] * (1. / pixman_fixed_1);
|
||||
t = ((dx * v.vector[0] + dy * v.vector[1]) -
|
||||
(dx * linear->p1.x + dy * linear->p1.y) * v2) * invden;
|
||||
inc = (dx * unit.vector[0] + dy * unit.vector[1]) * invden;
|
||||
}
|
||||
next_inc = 0;
|
||||
|
||||
if (((pixman_fixed_32_32_t )(inc * width)) == 0)
|
||||
{
|
||||
register uint32_t color;
|
||||
uint16_t dither_diff;
|
||||
uint16_t color16;
|
||||
uint16_t color16b;
|
||||
|
||||
color = _pixman_gradient_walker_pixel (&walker, t);
|
||||
color16 = dither_8888_to_0565(color, toggle);
|
||||
color16b = dither_8888_to_0565(color, toggle^1);
|
||||
// compute the difference
|
||||
dither_diff = color16 ^ color16b;
|
||||
while (buffer < end) {
|
||||
*buffer++ = color16;
|
||||
// use dither_diff to toggle between color16 and color16b
|
||||
color16 ^= dither_diff;
|
||||
toggle ^= 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
while (buffer < end)
|
||||
{
|
||||
if (!mask || *mask++)
|
||||
{
|
||||
*buffer = dither_8888_to_0565(_pixman_gradient_walker_pixel (&walker,
|
||||
t + next_inc),
|
||||
toggle);
|
||||
}
|
||||
toggle ^= 1;
|
||||
i++;
|
||||
next_inc = inc * i;
|
||||
buffer++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* projective transformation */
|
||||
double t;
|
||||
|
||||
t = 0;
|
||||
|
||||
while (buffer < end)
|
||||
{
|
||||
if (!mask || *mask++)
|
||||
{
|
||||
if (v.vector[2] != 0)
|
||||
{
|
||||
double invden, v2;
|
||||
|
||||
invden = pixman_fixed_1 * (double) pixman_fixed_1 /
|
||||
(l * (double) v.vector[2]);
|
||||
v2 = v.vector[2] * (1. / pixman_fixed_1);
|
||||
t = ((dx * v.vector[0] + dy * v.vector[1]) -
|
||||
(dx * linear->p1.x + dy * linear->p1.y) * v2) * invden;
|
||||
}
|
||||
|
||||
*buffer = dither_8888_to_0565(_pixman_gradient_walker_pixel (&walker, t),
|
||||
toggle);
|
||||
}
|
||||
toggle ^= 1;
|
||||
|
||||
++buffer;
|
||||
|
||||
v.vector[0] += unit.vector[0];
|
||||
v.vector[1] += unit.vector[1];
|
||||
v.vector[2] += unit.vector[2];
|
||||
}
|
||||
}
|
||||
|
||||
iter->y++;
|
||||
|
||||
return iter->buffer;
|
||||
}
|
||||
|
||||
static uint32_t *
|
||||
linear_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
uint32_t *buffer = linear_get_scanline_narrow (iter, NULL);
|
||||
|
||||
pixman_expand_to_float (
|
||||
(argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void
|
||||
_pixman_linear_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter)
|
||||
{
|
||||
// XXX: we can't use this optimization when dithering
|
||||
if (0 && linear_gradient_is_horizontal (
|
||||
iter->image, iter->x, iter->y, iter->width, iter->height))
|
||||
{
|
||||
if (iter->iter_flags & ITER_16)
|
||||
linear_get_scanline_16 (iter, NULL);
|
||||
else if (iter->iter_flags & ITER_NARROW)
|
||||
linear_get_scanline_narrow (iter, NULL);
|
||||
else
|
||||
linear_get_scanline_wide (iter, NULL);
|
||||
|
||||
iter->get_scanline = _pixman_iter_get_scanline_noop;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (iter->iter_flags & ITER_16)
|
||||
iter->get_scanline = linear_get_scanline_16;
|
||||
else if (iter->iter_flags & ITER_NARROW)
|
||||
iter->get_scanline = linear_get_scanline_narrow;
|
||||
else
|
||||
iter->get_scanline = linear_get_scanline_wide;
|
||||
}
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT pixman_image_t *
|
||||
pixman_image_create_linear_gradient (const pixman_point_fixed_t * p1,
|
||||
const pixman_point_fixed_t * p2,
|
||||
const pixman_gradient_stop_t *stops,
|
||||
int n_stops)
|
||||
{
|
||||
pixman_image_t *image;
|
||||
linear_gradient_t *linear;
|
||||
|
||||
image = _pixman_image_allocate ();
|
||||
|
||||
if (!image)
|
||||
return NULL;
|
||||
|
||||
linear = &image->linear;
|
||||
|
||||
if (!_pixman_init_gradient (&linear->common, stops, n_stops))
|
||||
{
|
||||
free (image);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
linear->p1 = *p1;
|
||||
linear->p2 = *p2;
|
||||
|
||||
image->type = LINEAR;
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
1073
gfx/cairo/libpixman/src/pixman-matrix.c
Normal file
1073
gfx/cairo/libpixman/src/pixman-matrix.c
Normal file
File diff suppressed because it is too large
Load diff
3373
gfx/cairo/libpixman/src/pixman-mips-dspr2-asm.S
Normal file
3373
gfx/cairo/libpixman/src/pixman-mips-dspr2-asm.S
Normal file
File diff suppressed because it is too large
Load diff
681
gfx/cairo/libpixman/src/pixman-mips-dspr2-asm.h
Normal file
681
gfx/cairo/libpixman/src/pixman-mips-dspr2-asm.h
Normal file
|
|
@ -0,0 +1,681 @@
|
|||
/*
|
||||
* Copyright (c) 2012
|
||||
* MIPS Technologies, Inc., California.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the MIPS Technologies, Inc., nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Author: Nemanja Lukic (nlukic@mips.com)
|
||||
*/
|
||||
|
||||
#ifndef PIXMAN_MIPS_DSPR2_ASM_H
|
||||
#define PIXMAN_MIPS_DSPR2_ASM_H
|
||||
|
||||
#define zero $0
|
||||
#define AT $1
|
||||
#define v0 $2
|
||||
#define v1 $3
|
||||
#define a0 $4
|
||||
#define a1 $5
|
||||
#define a2 $6
|
||||
#define a3 $7
|
||||
#define t0 $8
|
||||
#define t1 $9
|
||||
#define t2 $10
|
||||
#define t3 $11
|
||||
#define t4 $12
|
||||
#define t5 $13
|
||||
#define t6 $14
|
||||
#define t7 $15
|
||||
#define s0 $16
|
||||
#define s1 $17
|
||||
#define s2 $18
|
||||
#define s3 $19
|
||||
#define s4 $20
|
||||
#define s5 $21
|
||||
#define s6 $22
|
||||
#define s7 $23
|
||||
#define t8 $24
|
||||
#define t9 $25
|
||||
#define k0 $26
|
||||
#define k1 $27
|
||||
#define gp $28
|
||||
#define sp $29
|
||||
#define fp $30
|
||||
#define s8 $30
|
||||
#define ra $31
|
||||
|
||||
/*
|
||||
* LEAF_MIPS32R2 - declare leaf routine for MIPS32r2
|
||||
*/
|
||||
#define LEAF_MIPS32R2(symbol) \
|
||||
.globl symbol; \
|
||||
.align 2; \
|
||||
.type symbol, @function; \
|
||||
.ent symbol, 0; \
|
||||
symbol: .frame sp, 0, ra; \
|
||||
.set push; \
|
||||
.set arch=mips32r2; \
|
||||
.set noreorder; \
|
||||
.set noat;
|
||||
|
||||
/*
|
||||
* LEAF_MIPS32R2 - declare leaf routine for MIPS DSPr2
|
||||
*/
|
||||
#define LEAF_MIPS_DSPR2(symbol) \
|
||||
LEAF_MIPS32R2(symbol) \
|
||||
.set dspr2;
|
||||
|
||||
/*
|
||||
* END - mark end of function
|
||||
*/
|
||||
#define END(function) \
|
||||
.set pop; \
|
||||
.end function; \
|
||||
.size function,.-function
|
||||
|
||||
/*
|
||||
* Checks if stack offset is big enough for storing/restoring regs_num
|
||||
* number of register to/from stack. Stack offset must be greater than
|
||||
* or equal to the number of bytes needed for storing registers (regs_num*4).
|
||||
* Since MIPS ABI allows usage of first 16 bytes of stack frame (this is
|
||||
* preserved for input arguments of the functions, already stored in a0-a3),
|
||||
* stack size can be further optimized by utilizing this space.
|
||||
*/
|
||||
.macro CHECK_STACK_OFFSET regs_num, stack_offset
|
||||
.if \stack_offset < \regs_num * 4 - 16
|
||||
.error "Stack offset too small."
|
||||
.endif
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Saves set of registers on stack. Maximum number of registers that
|
||||
* can be saved on stack is limitted to 14 (a0-a3, v0-v1 and s0-s7).
|
||||
* Stack offset is number of bytes that are added to stack pointer (sp)
|
||||
* before registers are pushed in order to provide enough space on stack
|
||||
* (offset must be multiple of 4, and must be big enough, as described by
|
||||
* CHECK_STACK_OFFSET macro). This macro is intended to be used in
|
||||
* combination with RESTORE_REGS_FROM_STACK macro. Example:
|
||||
* SAVE_REGS_ON_STACK 4, v0, v1, s0, s1
|
||||
* RESTORE_REGS_FROM_STACK 4, v0, v1, s0, s1
|
||||
*/
|
||||
.macro SAVE_REGS_ON_STACK stack_offset = 0, r1, \
|
||||
r2 = 0, r3 = 0, r4 = 0, \
|
||||
r5 = 0, r6 = 0, r7 = 0, \
|
||||
r8 = 0, r9 = 0, r10 = 0, \
|
||||
r11 = 0, r12 = 0, r13 = 0, \
|
||||
r14 = 0
|
||||
.if (\stack_offset < 0) || (\stack_offset - (\stack_offset / 4) * 4)
|
||||
.error "Stack offset must be pozitive and multiple of 4."
|
||||
.endif
|
||||
.if \stack_offset != 0
|
||||
addiu sp, sp, -\stack_offset
|
||||
.endif
|
||||
sw \r1, 0(sp)
|
||||
.if \r2 != 0
|
||||
sw \r2, 4(sp)
|
||||
.endif
|
||||
.if \r3 != 0
|
||||
sw \r3, 8(sp)
|
||||
.endif
|
||||
.if \r4 != 0
|
||||
sw \r4, 12(sp)
|
||||
.endif
|
||||
.if \r5 != 0
|
||||
CHECK_STACK_OFFSET 5, \stack_offset
|
||||
sw \r5, 16(sp)
|
||||
.endif
|
||||
.if \r6 != 0
|
||||
CHECK_STACK_OFFSET 6, \stack_offset
|
||||
sw \r6, 20(sp)
|
||||
.endif
|
||||
.if \r7 != 0
|
||||
CHECK_STACK_OFFSET 7, \stack_offset
|
||||
sw \r7, 24(sp)
|
||||
.endif
|
||||
.if \r8 != 0
|
||||
CHECK_STACK_OFFSET 8, \stack_offset
|
||||
sw \r8, 28(sp)
|
||||
.endif
|
||||
.if \r9 != 0
|
||||
CHECK_STACK_OFFSET 9, \stack_offset
|
||||
sw \r9, 32(sp)
|
||||
.endif
|
||||
.if \r10 != 0
|
||||
CHECK_STACK_OFFSET 10, \stack_offset
|
||||
sw \r10, 36(sp)
|
||||
.endif
|
||||
.if \r11 != 0
|
||||
CHECK_STACK_OFFSET 11, \stack_offset
|
||||
sw \r11, 40(sp)
|
||||
.endif
|
||||
.if \r12 != 0
|
||||
CHECK_STACK_OFFSET 12, \stack_offset
|
||||
sw \r12, 44(sp)
|
||||
.endif
|
||||
.if \r13 != 0
|
||||
CHECK_STACK_OFFSET 13, \stack_offset
|
||||
sw \r13, 48(sp)
|
||||
.endif
|
||||
.if \r14 != 0
|
||||
CHECK_STACK_OFFSET 14, \stack_offset
|
||||
sw \r14, 52(sp)
|
||||
.endif
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Restores set of registers from stack. Maximum number of registers that
|
||||
* can be restored from stack is limitted to 14 (a0-a3, v0-v1 and s0-s7).
|
||||
* Stack offset is number of bytes that are added to stack pointer (sp)
|
||||
* after registers are restored (offset must be multiple of 4, and must
|
||||
* be big enough, as described by CHECK_STACK_OFFSET macro). This macro is
|
||||
* intended to be used in combination with RESTORE_REGS_FROM_STACK macro.
|
||||
* Example:
|
||||
* SAVE_REGS_ON_STACK 4, v0, v1, s0, s1
|
||||
* RESTORE_REGS_FROM_STACK 4, v0, v1, s0, s1
|
||||
*/
|
||||
.macro RESTORE_REGS_FROM_STACK stack_offset = 0, r1, \
|
||||
r2 = 0, r3 = 0, r4 = 0, \
|
||||
r5 = 0, r6 = 0, r7 = 0, \
|
||||
r8 = 0, r9 = 0, r10 = 0, \
|
||||
r11 = 0, r12 = 0, r13 = 0, \
|
||||
r14 = 0
|
||||
.if (\stack_offset < 0) || (\stack_offset - (\stack_offset/4)*4)
|
||||
.error "Stack offset must be pozitive and multiple of 4."
|
||||
.endif
|
||||
lw \r1, 0(sp)
|
||||
.if \r2 != 0
|
||||
lw \r2, 4(sp)
|
||||
.endif
|
||||
.if \r3 != 0
|
||||
lw \r3, 8(sp)
|
||||
.endif
|
||||
.if \r4 != 0
|
||||
lw \r4, 12(sp)
|
||||
.endif
|
||||
.if \r5 != 0
|
||||
CHECK_STACK_OFFSET 5, \stack_offset
|
||||
lw \r5, 16(sp)
|
||||
.endif
|
||||
.if \r6 != 0
|
||||
CHECK_STACK_OFFSET 6, \stack_offset
|
||||
lw \r6, 20(sp)
|
||||
.endif
|
||||
.if \r7 != 0
|
||||
CHECK_STACK_OFFSET 7, \stack_offset
|
||||
lw \r7, 24(sp)
|
||||
.endif
|
||||
.if \r8 != 0
|
||||
CHECK_STACK_OFFSET 8, \stack_offset
|
||||
lw \r8, 28(sp)
|
||||
.endif
|
||||
.if \r9 != 0
|
||||
CHECK_STACK_OFFSET 9, \stack_offset
|
||||
lw \r9, 32(sp)
|
||||
.endif
|
||||
.if \r10 != 0
|
||||
CHECK_STACK_OFFSET 10, \stack_offset
|
||||
lw \r10, 36(sp)
|
||||
.endif
|
||||
.if \r11 != 0
|
||||
CHECK_STACK_OFFSET 11, \stack_offset
|
||||
lw \r11, 40(sp)
|
||||
.endif
|
||||
.if \r12 != 0
|
||||
CHECK_STACK_OFFSET 12, \stack_offset
|
||||
lw \r12, 44(sp)
|
||||
.endif
|
||||
.if \r13 != 0
|
||||
CHECK_STACK_OFFSET 13, \stack_offset
|
||||
lw \r13, 48(sp)
|
||||
.endif
|
||||
.if \r14 != 0
|
||||
CHECK_STACK_OFFSET 14, \stack_offset
|
||||
lw \r14, 52(sp)
|
||||
.endif
|
||||
.if \stack_offset != 0
|
||||
addiu sp, sp, \stack_offset
|
||||
.endif
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Conversion of single r5g6b5 pixel (in_565) to single a8r8g8b8 pixel
|
||||
* returned in (out_8888) register. Requires two temporary registers
|
||||
* (scratch1 and scratch2).
|
||||
*/
|
||||
.macro CONVERT_1x0565_TO_1x8888 in_565, \
|
||||
out_8888, \
|
||||
scratch1, scratch2
|
||||
lui \out_8888, 0xff00
|
||||
sll \scratch1, \in_565, 0x3
|
||||
andi \scratch2, \scratch1, 0xff
|
||||
ext \scratch1, \in_565, 0x2, 0x3
|
||||
or \scratch1, \scratch2, \scratch1
|
||||
or \out_8888, \out_8888, \scratch1
|
||||
|
||||
sll \scratch1, \in_565, 0x5
|
||||
andi \scratch1, \scratch1, 0xfc00
|
||||
srl \scratch2, \in_565, 0x1
|
||||
andi \scratch2, \scratch2, 0x300
|
||||
or \scratch2, \scratch1, \scratch2
|
||||
or \out_8888, \out_8888, \scratch2
|
||||
|
||||
andi \scratch1, \in_565, 0xf800
|
||||
srl \scratch2, \scratch1, 0x5
|
||||
andi \scratch2, \scratch2, 0xff00
|
||||
or \scratch1, \scratch1, \scratch2
|
||||
sll \scratch1, \scratch1, 0x8
|
||||
or \out_8888, \out_8888, \scratch1
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Conversion of two r5g6b5 pixels (in1_565 and in2_565) to two a8r8g8b8 pixels
|
||||
* returned in (out1_8888 and out2_8888) registers. Requires four scratch
|
||||
* registers (scratch1 ... scratch4). It also requires maskG and maskB for
|
||||
* color component extractions. These masks must have following values:
|
||||
* li maskG, 0x07e007e0
|
||||
* li maskB, 0x001F001F
|
||||
*/
|
||||
.macro CONVERT_2x0565_TO_2x8888 in1_565, in2_565, \
|
||||
out1_8888, out2_8888, \
|
||||
maskG, maskB, \
|
||||
scratch1, scratch2, scratch3, scratch4
|
||||
sll \scratch1, \in1_565, 16
|
||||
or \scratch1, \scratch1, \in2_565
|
||||
lui \out2_8888, 0xff00
|
||||
ori \out2_8888, \out2_8888, 0xff00
|
||||
shrl.ph \scratch2, \scratch1, 11
|
||||
and \scratch3, \scratch1, \maskG
|
||||
shra.ph \scratch4, \scratch2, 2
|
||||
shll.ph \scratch2, \scratch2, 3
|
||||
shll.ph \scratch3, \scratch3, 5
|
||||
or \scratch2, \scratch2, \scratch4
|
||||
shrl.qb \scratch4, \scratch3, 6
|
||||
or \out2_8888, \out2_8888, \scratch2
|
||||
or \scratch3, \scratch3, \scratch4
|
||||
and \scratch1, \scratch1, \maskB
|
||||
shll.ph \scratch2, \scratch1, 3
|
||||
shra.ph \scratch4, \scratch1, 2
|
||||
or \scratch2, \scratch2, \scratch4
|
||||
or \scratch3, \scratch2, \scratch3
|
||||
precrq.ph.w \out1_8888, \out2_8888, \scratch3
|
||||
precr_sra.ph.w \out2_8888, \scratch3, 0
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Conversion of single a8r8g8b8 pixel (in_8888) to single r5g6b5 pixel
|
||||
* returned in (out_565) register. Requires two temporary registers
|
||||
* (scratch1 and scratch2).
|
||||
*/
|
||||
.macro CONVERT_1x8888_TO_1x0565 in_8888, \
|
||||
out_565, \
|
||||
scratch1, scratch2
|
||||
ext \out_565, \in_8888, 0x3, 0x5
|
||||
srl \scratch1, \in_8888, 0x5
|
||||
andi \scratch1, \scratch1, 0x07e0
|
||||
srl \scratch2, \in_8888, 0x8
|
||||
andi \scratch2, \scratch2, 0xf800
|
||||
or \out_565, \out_565, \scratch1
|
||||
or \out_565, \out_565, \scratch2
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Conversion of two a8r8g8b8 pixels (in1_8888 and in2_8888) to two r5g6b5
|
||||
* pixels returned in (out1_565 and out2_565) registers. Requires two temporary
|
||||
* registers (scratch1 and scratch2). It also requires maskR, maskG and maskB
|
||||
* for color component extractions. These masks must have following values:
|
||||
* li maskR, 0xf800f800
|
||||
* li maskG, 0x07e007e0
|
||||
* li maskB, 0x001F001F
|
||||
* Value of input register in2_8888 is lost.
|
||||
*/
|
||||
.macro CONVERT_2x8888_TO_2x0565 in1_8888, in2_8888, \
|
||||
out1_565, out2_565, \
|
||||
maskR, maskG, maskB, \
|
||||
scratch1, scratch2
|
||||
precrq.ph.w \scratch1, \in2_8888, \in1_8888
|
||||
precr_sra.ph.w \in2_8888, \in1_8888, 0
|
||||
shll.ph \scratch1, \scratch1, 8
|
||||
srl \in2_8888, \in2_8888, 3
|
||||
and \scratch2, \in2_8888, \maskB
|
||||
and \scratch1, \scratch1, \maskR
|
||||
srl \in2_8888, \in2_8888, 2
|
||||
and \out2_565, \in2_8888, \maskG
|
||||
or \out2_565, \out2_565, \scratch2
|
||||
or \out1_565, \out2_565, \scratch1
|
||||
srl \out2_565, \out1_565, 16
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Multiply pixel (a8) with single pixel (a8r8g8b8). It requires maskLSR needed
|
||||
* for rounding process. maskLSR must have following value:
|
||||
* li maskLSR, 0x00ff00ff
|
||||
*/
|
||||
.macro MIPS_UN8x4_MUL_UN8 s_8888, \
|
||||
m_8, \
|
||||
d_8888, \
|
||||
maskLSR, \
|
||||
scratch1, scratch2, scratch3
|
||||
replv.ph \m_8, \m_8 /* 0 | M | 0 | M */
|
||||
muleu_s.ph.qbl \scratch1, \s_8888, \m_8 /* A*M | R*M */
|
||||
muleu_s.ph.qbr \scratch2, \s_8888, \m_8 /* G*M | B*M */
|
||||
shra_r.ph \scratch3, \scratch1, 8
|
||||
shra_r.ph \d_8888, \scratch2, 8
|
||||
and \scratch3, \scratch3, \maskLSR /* 0 |A*M| 0 |R*M */
|
||||
and \d_8888, \d_8888, \maskLSR /* 0 |G*M| 0 |B*M */
|
||||
addq.ph \scratch1, \scratch1, \scratch3 /* A*M+A*M | R*M+R*M */
|
||||
addq.ph \scratch2, \scratch2, \d_8888 /* G*M+G*M | B*M+B*M */
|
||||
shra_r.ph \scratch1, \scratch1, 8
|
||||
shra_r.ph \scratch2, \scratch2, 8
|
||||
precr.qb.ph \d_8888, \scratch1, \scratch2
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Multiply two pixels (a8) with two pixels (a8r8g8b8). It requires maskLSR
|
||||
* needed for rounding process. maskLSR must have following value:
|
||||
* li maskLSR, 0x00ff00ff
|
||||
*/
|
||||
.macro MIPS_2xUN8x4_MUL_2xUN8 s1_8888, \
|
||||
s2_8888, \
|
||||
m1_8, \
|
||||
m2_8, \
|
||||
d1_8888, \
|
||||
d2_8888, \
|
||||
maskLSR, \
|
||||
scratch1, scratch2, scratch3, \
|
||||
scratch4, scratch5, scratch6
|
||||
replv.ph \m1_8, \m1_8 /* 0 | M1 | 0 | M1 */
|
||||
replv.ph \m2_8, \m2_8 /* 0 | M2 | 0 | M2 */
|
||||
muleu_s.ph.qbl \scratch1, \s1_8888, \m1_8 /* A1*M1 | R1*M1 */
|
||||
muleu_s.ph.qbr \scratch2, \s1_8888, \m1_8 /* G1*M1 | B1*M1 */
|
||||
muleu_s.ph.qbl \scratch3, \s2_8888, \m2_8 /* A2*M2 | R2*M2 */
|
||||
muleu_s.ph.qbr \scratch4, \s2_8888, \m2_8 /* G2*M2 | B2*M2 */
|
||||
shra_r.ph \scratch5, \scratch1, 8
|
||||
shra_r.ph \d1_8888, \scratch2, 8
|
||||
shra_r.ph \scratch6, \scratch3, 8
|
||||
shra_r.ph \d2_8888, \scratch4, 8
|
||||
and \scratch5, \scratch5, \maskLSR /* 0 |A1*M1| 0 |R1*M1 */
|
||||
and \d1_8888, \d1_8888, \maskLSR /* 0 |G1*M1| 0 |B1*M1 */
|
||||
and \scratch6, \scratch6, \maskLSR /* 0 |A2*M2| 0 |R2*M2 */
|
||||
and \d2_8888, \d2_8888, \maskLSR /* 0 |G2*M2| 0 |B2*M2 */
|
||||
addq.ph \scratch1, \scratch1, \scratch5
|
||||
addq.ph \scratch2, \scratch2, \d1_8888
|
||||
addq.ph \scratch3, \scratch3, \scratch6
|
||||
addq.ph \scratch4, \scratch4, \d2_8888
|
||||
shra_r.ph \scratch1, \scratch1, 8
|
||||
shra_r.ph \scratch2, \scratch2, 8
|
||||
shra_r.ph \scratch3, \scratch3, 8
|
||||
shra_r.ph \scratch4, \scratch4, 8
|
||||
precr.qb.ph \d1_8888, \scratch1, \scratch2
|
||||
precr.qb.ph \d2_8888, \scratch3, \scratch4
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Multiply pixel (a8r8g8b8) with single pixel (a8r8g8b8). It requires maskLSR
|
||||
* needed for rounding process. maskLSR must have following value:
|
||||
* li maskLSR, 0x00ff00ff
|
||||
*/
|
||||
.macro MIPS_UN8x4_MUL_UN8x4 s_8888, \
|
||||
m_8888, \
|
||||
d_8888, \
|
||||
maskLSR, \
|
||||
scratch1, scratch2, scratch3, scratch4
|
||||
preceu.ph.qbl \scratch1, \m_8888 /* 0 | A | 0 | R */
|
||||
preceu.ph.qbr \scratch2, \m_8888 /* 0 | G | 0 | B */
|
||||
muleu_s.ph.qbl \scratch3, \s_8888, \scratch1 /* A*A | R*R */
|
||||
muleu_s.ph.qbr \scratch4, \s_8888, \scratch2 /* G*G | B*B */
|
||||
shra_r.ph \scratch1, \scratch3, 8
|
||||
shra_r.ph \scratch2, \scratch4, 8
|
||||
and \scratch1, \scratch1, \maskLSR /* 0 |A*A| 0 |R*R */
|
||||
and \scratch2, \scratch2, \maskLSR /* 0 |G*G| 0 |B*B */
|
||||
addq.ph \scratch1, \scratch1, \scratch3
|
||||
addq.ph \scratch2, \scratch2, \scratch4
|
||||
shra_r.ph \scratch1, \scratch1, 8
|
||||
shra_r.ph \scratch2, \scratch2, 8
|
||||
precr.qb.ph \d_8888, \scratch1, \scratch2
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Multiply two pixels (a8r8g8b8) with two pixels (a8r8g8b8). It requires
|
||||
* maskLSR needed for rounding process. maskLSR must have following value:
|
||||
* li maskLSR, 0x00ff00ff
|
||||
*/
|
||||
|
||||
.macro MIPS_2xUN8x4_MUL_2xUN8x4 s1_8888, \
|
||||
s2_8888, \
|
||||
m1_8888, \
|
||||
m2_8888, \
|
||||
d1_8888, \
|
||||
d2_8888, \
|
||||
maskLSR, \
|
||||
scratch1, scratch2, scratch3, \
|
||||
scratch4, scratch5, scratch6
|
||||
preceu.ph.qbl \scratch1, \m1_8888 /* 0 | A | 0 | R */
|
||||
preceu.ph.qbr \scratch2, \m1_8888 /* 0 | G | 0 | B */
|
||||
preceu.ph.qbl \scratch3, \m2_8888 /* 0 | A | 0 | R */
|
||||
preceu.ph.qbr \scratch4, \m2_8888 /* 0 | G | 0 | B */
|
||||
muleu_s.ph.qbl \scratch5, \s1_8888, \scratch1 /* A*A | R*R */
|
||||
muleu_s.ph.qbr \scratch6, \s1_8888, \scratch2 /* G*G | B*B */
|
||||
muleu_s.ph.qbl \scratch1, \s2_8888, \scratch3 /* A*A | R*R */
|
||||
muleu_s.ph.qbr \scratch2, \s2_8888, \scratch4 /* G*G | B*B */
|
||||
shra_r.ph \scratch3, \scratch5, 8
|
||||
shra_r.ph \scratch4, \scratch6, 8
|
||||
shra_r.ph \d1_8888, \scratch1, 8
|
||||
shra_r.ph \d2_8888, \scratch2, 8
|
||||
and \scratch3, \scratch3, \maskLSR /* 0 |A*A| 0 |R*R */
|
||||
and \scratch4, \scratch4, \maskLSR /* 0 |G*G| 0 |B*B */
|
||||
and \d1_8888, \d1_8888, \maskLSR /* 0 |A*A| 0 |R*R */
|
||||
and \d2_8888, \d2_8888, \maskLSR /* 0 |G*G| 0 |B*B */
|
||||
addq.ph \scratch3, \scratch3, \scratch5
|
||||
addq.ph \scratch4, \scratch4, \scratch6
|
||||
addq.ph \d1_8888, \d1_8888, \scratch1
|
||||
addq.ph \d2_8888, \d2_8888, \scratch2
|
||||
shra_r.ph \scratch3, \scratch3, 8
|
||||
shra_r.ph \scratch4, \scratch4, 8
|
||||
shra_r.ph \scratch5, \d1_8888, 8
|
||||
shra_r.ph \scratch6, \d2_8888, 8
|
||||
precr.qb.ph \d1_8888, \scratch3, \scratch4
|
||||
precr.qb.ph \d2_8888, \scratch5, \scratch6
|
||||
.endm
|
||||
|
||||
/*
|
||||
* OVER operation on single a8r8g8b8 source pixel (s_8888) and single a8r8g8b8
|
||||
* destination pixel (d_8888) using a8 mask (m_8). It also requires maskLSR
|
||||
* needed for rounding process. maskLSR must have following value:
|
||||
* li maskLSR, 0x00ff00ff
|
||||
*/
|
||||
.macro OVER_8888_8_8888 s_8888, \
|
||||
m_8, \
|
||||
d_8888, \
|
||||
out_8888, \
|
||||
maskLSR, \
|
||||
scratch1, scratch2, scratch3, scratch4
|
||||
MIPS_UN8x4_MUL_UN8 \s_8888, \m_8, \
|
||||
\scratch1, \maskLSR, \
|
||||
\scratch2, \scratch3, \scratch4
|
||||
|
||||
not \scratch2, \scratch1
|
||||
srl \scratch2, \scratch2, 24
|
||||
|
||||
MIPS_UN8x4_MUL_UN8 \d_8888, \scratch2, \
|
||||
\d_8888, \maskLSR, \
|
||||
\scratch3, \scratch4, \out_8888
|
||||
|
||||
addu_s.qb \out_8888, \d_8888, \scratch1
|
||||
.endm
|
||||
|
||||
/*
|
||||
* OVER operation on two a8r8g8b8 source pixels (s1_8888 and s2_8888) and two
|
||||
* a8r8g8b8 destination pixels (d1_8888 and d2_8888) using a8 masks (m1_8 and
|
||||
* m2_8). It also requires maskLSR needed for rounding process. maskLSR must
|
||||
* have following value:
|
||||
* li maskLSR, 0x00ff00ff
|
||||
*/
|
||||
.macro OVER_2x8888_2x8_2x8888 s1_8888, \
|
||||
s2_8888, \
|
||||
m1_8, \
|
||||
m2_8, \
|
||||
d1_8888, \
|
||||
d2_8888, \
|
||||
out1_8888, \
|
||||
out2_8888, \
|
||||
maskLSR, \
|
||||
scratch1, scratch2, scratch3, \
|
||||
scratch4, scratch5, scratch6
|
||||
MIPS_2xUN8x4_MUL_2xUN8 \s1_8888, \s2_8888, \
|
||||
\m1_8, \m2_8, \
|
||||
\scratch1, \scratch2, \
|
||||
\maskLSR, \
|
||||
\scratch3, \scratch4, \out1_8888, \
|
||||
\out2_8888, \scratch5, \scratch6
|
||||
|
||||
not \scratch3, \scratch1
|
||||
srl \scratch3, \scratch3, 24
|
||||
not \scratch4, \scratch2
|
||||
srl \scratch4, \scratch4, 24
|
||||
|
||||
MIPS_2xUN8x4_MUL_2xUN8 \d1_8888, \d2_8888, \
|
||||
\scratch3, \scratch4, \
|
||||
\d1_8888, \d2_8888, \
|
||||
\maskLSR, \
|
||||
\scratch5, \scratch6, \out1_8888, \
|
||||
\out2_8888, \scratch3, \scratch4
|
||||
|
||||
addu_s.qb \out1_8888, \d1_8888, \scratch1
|
||||
addu_s.qb \out2_8888, \d2_8888, \scratch2
|
||||
.endm
|
||||
|
||||
/*
|
||||
* OVER operation on single a8r8g8b8 source pixel (s_8888) and single a8r8g8b8
|
||||
* destination pixel (d_8888). It also requires maskLSR needed for rounding
|
||||
* process. maskLSR must have following value:
|
||||
* li maskLSR, 0x00ff00ff
|
||||
*/
|
||||
.macro OVER_8888_8888 s_8888, \
|
||||
d_8888, \
|
||||
out_8888, \
|
||||
maskLSR, \
|
||||
scratch1, scratch2, scratch3, scratch4
|
||||
not \scratch1, \s_8888
|
||||
srl \scratch1, \scratch1, 24
|
||||
|
||||
MIPS_UN8x4_MUL_UN8 \d_8888, \scratch1, \
|
||||
\out_8888, \maskLSR, \
|
||||
\scratch2, \scratch3, \scratch4
|
||||
|
||||
addu_s.qb \out_8888, \out_8888, \s_8888
|
||||
.endm
|
||||
|
||||
.macro MIPS_UN8x4_MUL_UN8_ADD_UN8x4 s_8888, \
|
||||
m_8, \
|
||||
d_8888, \
|
||||
out_8888, \
|
||||
maskLSR, \
|
||||
scratch1, scratch2, scratch3
|
||||
MIPS_UN8x4_MUL_UN8 \s_8888, \m_8, \
|
||||
\out_8888, \maskLSR, \
|
||||
\scratch1, \scratch2, \scratch3
|
||||
|
||||
addu_s.qb \out_8888, \out_8888, \d_8888
|
||||
.endm
|
||||
|
||||
.macro MIPS_2xUN8x4_MUL_2xUN8_ADD_2xUN8x4 s1_8888, \
|
||||
s2_8888, \
|
||||
m1_8, \
|
||||
m2_8, \
|
||||
d1_8888, \
|
||||
d2_8888, \
|
||||
out1_8888, \
|
||||
out2_8888, \
|
||||
maskLSR, \
|
||||
scratch1, scratch2, scratch3, \
|
||||
scratch4, scratch5, scratch6
|
||||
MIPS_2xUN8x4_MUL_2xUN8 \s1_8888, \s2_8888, \
|
||||
\m1_8, \m2_8, \
|
||||
\out1_8888, \out2_8888, \
|
||||
\maskLSR, \
|
||||
\scratch1, \scratch2, \scratch3, \
|
||||
\scratch4, \scratch5, \scratch6
|
||||
|
||||
addu_s.qb \out1_8888, \out1_8888, \d1_8888
|
||||
addu_s.qb \out2_8888, \out2_8888, \d2_8888
|
||||
.endm
|
||||
|
||||
.macro BILINEAR_INTERPOLATE_SINGLE_PIXEL tl, tr, bl, br, \
|
||||
scratch1, scratch2, \
|
||||
alpha, red, green, blue \
|
||||
wt1, wt2, wb1, wb2
|
||||
andi \scratch1, \tl, 0xff
|
||||
andi \scratch2, \tr, 0xff
|
||||
andi \alpha, \bl, 0xff
|
||||
andi \red, \br, 0xff
|
||||
|
||||
multu $ac0, \wt1, \scratch1
|
||||
maddu $ac0, \wt2, \scratch2
|
||||
maddu $ac0, \wb1, \alpha
|
||||
maddu $ac0, \wb2, \red
|
||||
|
||||
ext \scratch1, \tl, 8, 8
|
||||
ext \scratch2, \tr, 8, 8
|
||||
ext \alpha, \bl, 8, 8
|
||||
ext \red, \br, 8, 8
|
||||
|
||||
multu $ac1, \wt1, \scratch1
|
||||
maddu $ac1, \wt2, \scratch2
|
||||
maddu $ac1, \wb1, \alpha
|
||||
maddu $ac1, \wb2, \red
|
||||
|
||||
ext \scratch1, \tl, 16, 8
|
||||
ext \scratch2, \tr, 16, 8
|
||||
ext \alpha, \bl, 16, 8
|
||||
ext \red, \br, 16, 8
|
||||
|
||||
mflo \blue, $ac0
|
||||
|
||||
multu $ac2, \wt1, \scratch1
|
||||
maddu $ac2, \wt2, \scratch2
|
||||
maddu $ac2, \wb1, \alpha
|
||||
maddu $ac2, \wb2, \red
|
||||
|
||||
ext \scratch1, \tl, 24, 8
|
||||
ext \scratch2, \tr, 24, 8
|
||||
ext \alpha, \bl, 24, 8
|
||||
ext \red, \br, 24, 8
|
||||
|
||||
mflo \green, $ac1
|
||||
|
||||
multu $ac3, \wt1, \scratch1
|
||||
maddu $ac3, \wt2, \scratch2
|
||||
maddu $ac3, \wb1, \alpha
|
||||
maddu $ac3, \wb2, \red
|
||||
|
||||
mflo \red, $ac2
|
||||
mflo \alpha, $ac3
|
||||
|
||||
precr.qb.ph \alpha, \alpha, \red
|
||||
precr.qb.ph \scratch1, \green, \blue
|
||||
precrq.qb.ph \tl, \alpha, \scratch1
|
||||
.endm
|
||||
|
||||
#endif //PIXMAN_MIPS_DSPR2_ASM_H
|
||||
411
gfx/cairo/libpixman/src/pixman-mips-dspr2.c
Normal file
411
gfx/cairo/libpixman/src/pixman-mips-dspr2.c
Normal file
|
|
@ -0,0 +1,411 @@
|
|||
/*
|
||||
* Copyright (c) 2012
|
||||
* MIPS Technologies, Inc., California.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the MIPS Technologies, Inc., nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Author: Nemanja Lukic (nlukic@mips.com)
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "pixman-private.h"
|
||||
#include "pixman-mips-dspr2.h"
|
||||
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, src_x888_8888,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, src_8888_0565,
|
||||
uint32_t, 1, uint16_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, src_0565_8888,
|
||||
uint16_t, 1, uint32_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (DO_FAST_MEMCPY, src_0565_0565,
|
||||
uint16_t, 1, uint16_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (DO_FAST_MEMCPY, src_8888_8888,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (DO_FAST_MEMCPY, src_0888_0888,
|
||||
uint8_t, 3, uint8_t, 3)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, over_8888_8888,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, add_8_8,
|
||||
uint8_t, 1, uint8_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, add_8888_8888,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, out_reverse_8_0565,
|
||||
uint8_t, 1, uint16_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, out_reverse_8_8888,
|
||||
uint8_t, 1, uint32_t, 1)
|
||||
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (0, src_n_8_8888,
|
||||
uint8_t, 1, uint32_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (0, src_n_8_8,
|
||||
uint8_t, 1, uint8_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8888_8888_ca,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8888_0565_ca,
|
||||
uint32_t, 1, uint16_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8_8888,
|
||||
uint8_t, 1, uint32_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8_0565,
|
||||
uint8_t, 1, uint16_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, add_n_8_8,
|
||||
uint8_t, 1, uint8_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, add_n_8_8888,
|
||||
uint8_t, 1, uint32_t, 1)
|
||||
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, over_8888_n_8888,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, over_8888_n_0565,
|
||||
uint32_t, 1, uint16_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, over_0565_n_0565,
|
||||
uint16_t, 1, uint16_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, add_8888_n_8888,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_N_DST (SKIP_ZERO_SRC, over_n_0565,
|
||||
uint16_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_N_DST (SKIP_ZERO_SRC, over_n_8888,
|
||||
uint32_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_N_DST (SKIP_ZERO_SRC, over_reverse_n_8888,
|
||||
uint32_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_N_DST (0, in_n_8,
|
||||
uint8_t, 1)
|
||||
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (add_8_8_8, uint8_t, 1,
|
||||
uint8_t, 1, uint8_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (add_8888_8_8888, uint32_t, 1,
|
||||
uint8_t, 1, uint32_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (add_8888_8888_8888, uint32_t, 1,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (add_0565_8_0565, uint16_t, 1,
|
||||
uint8_t, 1, uint16_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (over_8888_8_8888, uint32_t, 1,
|
||||
uint8_t, 1, uint32_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (over_8888_8_0565, uint32_t, 1,
|
||||
uint8_t, 1, uint16_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (over_0565_8_0565, uint16_t, 1,
|
||||
uint8_t, 1, uint16_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (over_8888_8888_8888, uint32_t, 1,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
|
||||
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (0, 8888_8888, SRC,
|
||||
uint32_t, uint32_t)
|
||||
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (0, 8888_0565, SRC,
|
||||
uint32_t, uint16_t)
|
||||
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (0, 0565_8888, SRC,
|
||||
uint16_t, uint32_t)
|
||||
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (0, 0565_0565, SRC,
|
||||
uint16_t, uint16_t)
|
||||
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (SKIP_ZERO_SRC, 8888_8888, OVER,
|
||||
uint32_t, uint32_t)
|
||||
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (SKIP_ZERO_SRC, 8888_8888, ADD,
|
||||
uint32_t, uint32_t)
|
||||
|
||||
PIXMAN_MIPS_BIND_SCALED_NEAREST_SRC_A8_DST (SKIP_ZERO_SRC, 8888_8_0565,
|
||||
OVER, uint32_t, uint16_t)
|
||||
PIXMAN_MIPS_BIND_SCALED_NEAREST_SRC_A8_DST (SKIP_ZERO_SRC, 0565_8_0565,
|
||||
OVER, uint16_t, uint16_t)
|
||||
|
||||
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (0, 8888_8_8888, SRC,
|
||||
uint32_t, uint32_t)
|
||||
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (0, 8888_8_0565, SRC,
|
||||
uint32_t, uint16_t)
|
||||
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (0, 0565_8_x888, SRC,
|
||||
uint16_t, uint32_t)
|
||||
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (0, 0565_8_0565, SRC,
|
||||
uint16_t, uint16_t)
|
||||
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (SKIP_ZERO_SRC, 8888_8_8888, OVER,
|
||||
uint32_t, uint32_t)
|
||||
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (SKIP_ZERO_SRC, 8888_8_8888, ADD,
|
||||
uint32_t, uint32_t)
|
||||
|
||||
static pixman_bool_t
|
||||
mips_dspr2_fill (pixman_implementation_t *imp,
|
||||
uint32_t * bits,
|
||||
int stride,
|
||||
int bpp,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
uint32_t _xor)
|
||||
{
|
||||
uint8_t *byte_line;
|
||||
uint32_t byte_width;
|
||||
switch (bpp)
|
||||
{
|
||||
case 16:
|
||||
stride = stride * (int) sizeof (uint32_t) / 2;
|
||||
byte_line = (uint8_t *)(((uint16_t *)bits) + stride * y + x);
|
||||
byte_width = width * 2;
|
||||
stride *= 2;
|
||||
|
||||
while (height--)
|
||||
{
|
||||
uint8_t *dst = byte_line;
|
||||
byte_line += stride;
|
||||
pixman_fill_buff16_mips (dst, byte_width, _xor & 0xffff);
|
||||
}
|
||||
return TRUE;
|
||||
case 32:
|
||||
stride = stride * (int) sizeof (uint32_t) / 4;
|
||||
byte_line = (uint8_t *)(((uint32_t *)bits) + stride * y + x);
|
||||
byte_width = width * 4;
|
||||
stride *= 4;
|
||||
|
||||
while (height--)
|
||||
{
|
||||
uint8_t *dst = byte_line;
|
||||
byte_line += stride;
|
||||
pixman_fill_buff32_mips (dst, byte_width, _xor);
|
||||
}
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static pixman_bool_t
|
||||
mips_dspr2_blt (pixman_implementation_t *imp,
|
||||
uint32_t * src_bits,
|
||||
uint32_t * dst_bits,
|
||||
int src_stride,
|
||||
int dst_stride,
|
||||
int src_bpp,
|
||||
int dst_bpp,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dest_x,
|
||||
int dest_y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
if (src_bpp != dst_bpp)
|
||||
return FALSE;
|
||||
|
||||
uint8_t *src_bytes;
|
||||
uint8_t *dst_bytes;
|
||||
uint32_t byte_width;
|
||||
|
||||
switch (src_bpp)
|
||||
{
|
||||
case 16:
|
||||
src_stride = src_stride * (int) sizeof (uint32_t) / 2;
|
||||
dst_stride = dst_stride * (int) sizeof (uint32_t) / 2;
|
||||
src_bytes =(uint8_t *)(((uint16_t *)src_bits)
|
||||
+ src_stride * (src_y) + (src_x));
|
||||
dst_bytes = (uint8_t *)(((uint16_t *)dst_bits)
|
||||
+ dst_stride * (dest_y) + (dest_x));
|
||||
byte_width = width * 2;
|
||||
src_stride *= 2;
|
||||
dst_stride *= 2;
|
||||
|
||||
while (height--)
|
||||
{
|
||||
uint8_t *src = src_bytes;
|
||||
uint8_t *dst = dst_bytes;
|
||||
src_bytes += src_stride;
|
||||
dst_bytes += dst_stride;
|
||||
pixman_mips_fast_memcpy (dst, src, byte_width);
|
||||
}
|
||||
return TRUE;
|
||||
case 32:
|
||||
src_stride = src_stride * (int) sizeof (uint32_t) / 4;
|
||||
dst_stride = dst_stride * (int) sizeof (uint32_t) / 4;
|
||||
src_bytes = (uint8_t *)(((uint32_t *)src_bits)
|
||||
+ src_stride * (src_y) + (src_x));
|
||||
dst_bytes = (uint8_t *)(((uint32_t *)dst_bits)
|
||||
+ dst_stride * (dest_y) + (dest_x));
|
||||
byte_width = width * 4;
|
||||
src_stride *= 4;
|
||||
dst_stride *= 4;
|
||||
|
||||
while (height--)
|
||||
{
|
||||
uint8_t *src = src_bytes;
|
||||
uint8_t *dst = dst_bytes;
|
||||
src_bytes += src_stride;
|
||||
dst_bytes += dst_stride;
|
||||
pixman_mips_fast_memcpy (dst, src, byte_width);
|
||||
}
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static const pixman_fast_path_t mips_dspr2_fast_paths[] =
|
||||
{
|
||||
PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, r5g6b5, mips_composite_src_0565_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, b5g6r5, mips_composite_src_0565_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, r5g6b5, mips_composite_src_8888_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, r5g6b5, mips_composite_src_8888_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, b5g6r5, mips_composite_src_8888_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, b5g6r5, mips_composite_src_8888_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, a8r8g8b8, mips_composite_src_0565_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, x8r8g8b8, mips_composite_src_0565_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, a8b8g8r8, mips_composite_src_0565_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, x8b8g8r8, mips_composite_src_0565_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, x8r8g8b8, mips_composite_src_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, x8r8g8b8, mips_composite_src_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, x8b8g8r8, mips_composite_src_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, x8b8g8r8, mips_composite_src_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, a8r8g8b8, mips_composite_src_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, a8b8g8r8, mips_composite_src_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, a8r8g8b8, mips_composite_src_x888_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, a8b8g8r8, mips_composite_src_x888_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, r8g8b8, null, r8g8b8, mips_composite_src_0888_0888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8r8g8b8, mips_composite_src_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8r8g8b8, mips_composite_src_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8b8g8r8, mips_composite_src_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8b8g8r8, mips_composite_src_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8, mips_composite_src_n_8_8),
|
||||
|
||||
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, a8r8g8b8, mips_composite_over_n_8888_8888_ca),
|
||||
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, x8r8g8b8, mips_composite_over_n_8888_8888_ca),
|
||||
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, a8b8g8r8, mips_composite_over_n_8888_8888_ca),
|
||||
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, x8b8g8r8, mips_composite_over_n_8888_8888_ca),
|
||||
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, r5g6b5, mips_composite_over_n_8888_0565_ca),
|
||||
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, b5g6r5, mips_composite_over_n_8888_0565_ca),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8r8g8b8, mips_composite_over_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8r8g8b8, mips_composite_over_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8b8g8r8, mips_composite_over_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8b8g8r8, mips_composite_over_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, a8, r5g6b5, mips_composite_over_n_8_0565),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, a8, b5g6r5, mips_composite_over_n_8_0565),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, null, r5g6b5, mips_composite_over_n_0565),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, null, a8r8g8b8, mips_composite_over_n_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, null, x8r8g8b8, mips_composite_over_n_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, a8r8g8b8, mips_composite_over_8888_n_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, x8r8g8b8, mips_composite_over_8888_n_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, r5g6b5, mips_composite_over_8888_n_0565),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, solid, b5g6r5, mips_composite_over_8888_n_0565),
|
||||
PIXMAN_STD_FAST_PATH (OVER, r5g6b5, solid, r5g6b5, mips_composite_over_0565_n_0565),
|
||||
PIXMAN_STD_FAST_PATH (OVER, b5g6r5, solid, b5g6r5, mips_composite_over_0565_n_0565),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, a8r8g8b8, mips_composite_over_8888_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, x8r8g8b8, mips_composite_over_8888_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, a8b8g8r8, mips_composite_over_8888_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, x8b8g8r8, mips_composite_over_8888_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, r5g6b5, mips_composite_over_8888_8_0565),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, b5g6r5, mips_composite_over_8888_8_0565),
|
||||
PIXMAN_STD_FAST_PATH (OVER, r5g6b5, a8, r5g6b5, mips_composite_over_0565_8_0565),
|
||||
PIXMAN_STD_FAST_PATH (OVER, b5g6r5, a8, b5g6r5, mips_composite_over_0565_8_0565),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, a8r8g8b8, mips_composite_over_8888_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, mips_composite_over_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, mips_composite_over_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, mips_composite_over_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, mips_composite_over_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8, mips_composite_add_n_8_8),
|
||||
PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8r8g8b8, mips_composite_add_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8b8g8r8, mips_composite_add_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (ADD, a8, a8, a8, mips_composite_add_8_8_8),
|
||||
PIXMAN_STD_FAST_PATH (ADD, r5g6b5, a8, r5g6b5, mips_composite_add_0565_8_0565),
|
||||
PIXMAN_STD_FAST_PATH (ADD, b5g6r5, a8, b5g6r5, mips_composite_add_0565_8_0565),
|
||||
PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, a8, a8r8g8b8, mips_composite_add_8888_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, a8, a8b8g8r8, mips_composite_add_8888_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, a8r8g8b8, mips_composite_add_8888_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, solid, a8r8g8b8, mips_composite_add_8888_n_8888),
|
||||
PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, solid, a8b8g8r8, mips_composite_add_8888_n_8888),
|
||||
PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, mips_composite_add_8_8),
|
||||
PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, null, a8r8g8b8, mips_composite_add_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, null, a8b8g8r8, mips_composite_add_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, r5g6b5, mips_composite_out_reverse_8_0565),
|
||||
PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, b5g6r5, mips_composite_out_reverse_8_0565),
|
||||
PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, a8r8g8b8, mips_composite_out_reverse_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, a8b8g8r8, mips_composite_out_reverse_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8r8g8b8, mips_composite_over_reverse_n_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8b8g8r8, mips_composite_over_reverse_n_8888),
|
||||
PIXMAN_STD_FAST_PATH (IN, solid, null, a8, mips_composite_in_n_8),
|
||||
|
||||
PIXMAN_MIPS_SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, a8r8g8b8, r5g6b5, mips_8888_8_0565),
|
||||
PIXMAN_MIPS_SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, a8b8g8r8, b5g6r5, mips_8888_8_0565),
|
||||
|
||||
PIXMAN_MIPS_SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, r5g6b5, r5g6b5, mips_0565_8_0565),
|
||||
PIXMAN_MIPS_SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, b5g6r5, b5g6r5, mips_0565_8_0565),
|
||||
|
||||
SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, mips_8888_8888),
|
||||
SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, mips_8888_8888),
|
||||
SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, mips_8888_8888),
|
||||
|
||||
SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, r5g6b5, mips_8888_0565),
|
||||
SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, r5g6b5, mips_8888_0565),
|
||||
|
||||
SIMPLE_BILINEAR_FAST_PATH (SRC, r5g6b5, x8r8g8b8, mips_0565_8888),
|
||||
SIMPLE_BILINEAR_FAST_PATH (SRC, r5g6b5, r5g6b5, mips_0565_0565),
|
||||
|
||||
SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, mips_8888_8888),
|
||||
SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, mips_8888_8888),
|
||||
|
||||
SIMPLE_BILINEAR_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, mips_8888_8888),
|
||||
SIMPLE_BILINEAR_FAST_PATH (ADD, a8r8g8b8, x8r8g8b8, mips_8888_8888),
|
||||
|
||||
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, mips_8888_8_8888),
|
||||
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, mips_8888_8_8888),
|
||||
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, mips_8888_8_8888),
|
||||
|
||||
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, a8r8g8b8, r5g6b5, mips_8888_8_0565),
|
||||
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, x8r8g8b8, r5g6b5, mips_8888_8_0565),
|
||||
|
||||
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, r5g6b5, x8r8g8b8, mips_0565_8_x888),
|
||||
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, r5g6b5, r5g6b5, mips_0565_8_0565),
|
||||
|
||||
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, mips_8888_8_8888),
|
||||
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, mips_8888_8_8888),
|
||||
|
||||
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, mips_8888_8_8888),
|
||||
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (ADD, a8r8g8b8, x8r8g8b8, mips_8888_8_8888),
|
||||
{ PIXMAN_OP_NONE },
|
||||
};
|
||||
|
||||
static void
|
||||
mips_dspr2_combine_over_u (pixman_implementation_t *imp,
|
||||
pixman_op_t op,
|
||||
uint32_t * dest,
|
||||
const uint32_t * src,
|
||||
const uint32_t * mask,
|
||||
int width)
|
||||
{
|
||||
if (mask)
|
||||
pixman_composite_over_8888_8888_8888_asm_mips (
|
||||
dest, (uint32_t *)src, (uint32_t *)mask, width);
|
||||
else
|
||||
pixman_composite_over_8888_8888_asm_mips (
|
||||
dest, (uint32_t *)src, width);
|
||||
}
|
||||
|
||||
pixman_implementation_t *
|
||||
_pixman_implementation_create_mips_dspr2 (pixman_implementation_t *fallback)
|
||||
{
|
||||
pixman_implementation_t *imp =
|
||||
_pixman_implementation_create (fallback, mips_dspr2_fast_paths);
|
||||
|
||||
imp->combine_32[PIXMAN_OP_OVER] = mips_dspr2_combine_over_u;
|
||||
|
||||
imp->blt = mips_dspr2_blt;
|
||||
imp->fill = mips_dspr2_fill;
|
||||
|
||||
return imp;
|
||||
}
|
||||
396
gfx/cairo/libpixman/src/pixman-mips-dspr2.h
Normal file
396
gfx/cairo/libpixman/src/pixman-mips-dspr2.h
Normal file
|
|
@ -0,0 +1,396 @@
|
|||
/*
|
||||
* Copyright (c) 2012
|
||||
* MIPS Technologies, Inc., California.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the MIPS Technologies, Inc., nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Author: Nemanja Lukic (nlukic@mips.com)
|
||||
*/
|
||||
|
||||
#ifndef PIXMAN_MIPS_DSPR2_H
|
||||
#define PIXMAN_MIPS_DSPR2_H
|
||||
|
||||
#include "pixman-private.h"
|
||||
#include "pixman-inlines.h"
|
||||
|
||||
#define SKIP_ZERO_SRC 1
|
||||
#define SKIP_ZERO_MASK 2
|
||||
#define DO_FAST_MEMCPY 3
|
||||
|
||||
void
|
||||
pixman_mips_fast_memcpy (void *dst, void *src, uint32_t n_bytes);
|
||||
void
|
||||
pixman_fill_buff16_mips (void *dst, uint32_t n_bytes, uint16_t value);
|
||||
void
|
||||
pixman_fill_buff32_mips (void *dst, uint32_t n_bytes, uint32_t value);
|
||||
|
||||
/****************************************************************/
|
||||
|
||||
#define PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST(flags, name, \
|
||||
src_type, src_cnt, \
|
||||
dst_type, dst_cnt) \
|
||||
void \
|
||||
pixman_composite_##name##_asm_mips (dst_type *dst, \
|
||||
src_type *src, \
|
||||
int32_t w); \
|
||||
\
|
||||
static void \
|
||||
mips_composite_##name (pixman_implementation_t *imp, \
|
||||
pixman_composite_info_t *info) \
|
||||
{ \
|
||||
PIXMAN_COMPOSITE_ARGS (info); \
|
||||
dst_type *dst_line, *dst; \
|
||||
src_type *src_line, *src; \
|
||||
int32_t dst_stride, src_stride; \
|
||||
int bpp = PIXMAN_FORMAT_BPP (dest_image->bits.format) / 8; \
|
||||
\
|
||||
PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, src_type, \
|
||||
src_stride, src_line, src_cnt); \
|
||||
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
|
||||
dst_stride, dst_line, dst_cnt); \
|
||||
\
|
||||
while (height--) \
|
||||
{ \
|
||||
dst = dst_line; \
|
||||
dst_line += dst_stride; \
|
||||
src = src_line; \
|
||||
src_line += src_stride; \
|
||||
\
|
||||
if (flags == DO_FAST_MEMCPY) \
|
||||
pixman_mips_fast_memcpy (dst, src, width * bpp); \
|
||||
else \
|
||||
pixman_composite_##name##_asm_mips (dst, src, width); \
|
||||
} \
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
|
||||
#define PIXMAN_MIPS_BIND_FAST_PATH_N_DST(flags, name, \
|
||||
dst_type, dst_cnt) \
|
||||
void \
|
||||
pixman_composite_##name##_asm_mips (dst_type *dst, \
|
||||
uint32_t src, \
|
||||
int32_t w); \
|
||||
\
|
||||
static void \
|
||||
mips_composite_##name (pixman_implementation_t *imp, \
|
||||
pixman_composite_info_t *info) \
|
||||
{ \
|
||||
PIXMAN_COMPOSITE_ARGS (info); \
|
||||
dst_type *dst_line, *dst; \
|
||||
int32_t dst_stride; \
|
||||
uint32_t src; \
|
||||
\
|
||||
src = _pixman_image_get_solid ( \
|
||||
imp, src_image, dest_image->bits.format); \
|
||||
\
|
||||
if ((flags & SKIP_ZERO_SRC) && src == 0) \
|
||||
return; \
|
||||
\
|
||||
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
|
||||
dst_stride, dst_line, dst_cnt); \
|
||||
\
|
||||
while (height--) \
|
||||
{ \
|
||||
dst = dst_line; \
|
||||
dst_line += dst_stride; \
|
||||
\
|
||||
pixman_composite_##name##_asm_mips (dst, src, width); \
|
||||
} \
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
|
||||
#define PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST(flags, name, \
|
||||
mask_type, mask_cnt, \
|
||||
dst_type, dst_cnt) \
|
||||
void \
|
||||
pixman_composite_##name##_asm_mips (dst_type *dst, \
|
||||
uint32_t src, \
|
||||
mask_type *mask, \
|
||||
int32_t w); \
|
||||
\
|
||||
static void \
|
||||
mips_composite_##name (pixman_implementation_t *imp, \
|
||||
pixman_composite_info_t *info) \
|
||||
{ \
|
||||
PIXMAN_COMPOSITE_ARGS (info); \
|
||||
dst_type *dst_line, *dst; \
|
||||
mask_type *mask_line, *mask; \
|
||||
int32_t dst_stride, mask_stride; \
|
||||
uint32_t src; \
|
||||
\
|
||||
src = _pixman_image_get_solid ( \
|
||||
imp, src_image, dest_image->bits.format); \
|
||||
\
|
||||
if ((flags & SKIP_ZERO_SRC) && src == 0) \
|
||||
return; \
|
||||
\
|
||||
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
|
||||
dst_stride, dst_line, dst_cnt); \
|
||||
PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type, \
|
||||
mask_stride, mask_line, mask_cnt); \
|
||||
\
|
||||
while (height--) \
|
||||
{ \
|
||||
dst = dst_line; \
|
||||
dst_line += dst_stride; \
|
||||
mask = mask_line; \
|
||||
mask_line += mask_stride; \
|
||||
pixman_composite_##name##_asm_mips (dst, src, mask, width); \
|
||||
} \
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
|
||||
#define PIXMAN_MIPS_BIND_FAST_PATH_SRC_N_DST(flags, name, \
|
||||
src_type, src_cnt, \
|
||||
dst_type, dst_cnt) \
|
||||
void \
|
||||
pixman_composite_##name##_asm_mips (dst_type *dst, \
|
||||
src_type *src, \
|
||||
uint32_t mask, \
|
||||
int32_t w); \
|
||||
\
|
||||
static void \
|
||||
mips_composite_##name (pixman_implementation_t *imp, \
|
||||
pixman_composite_info_t *info) \
|
||||
{ \
|
||||
PIXMAN_COMPOSITE_ARGS (info); \
|
||||
dst_type *dst_line, *dst; \
|
||||
src_type *src_line, *src; \
|
||||
int32_t dst_stride, src_stride; \
|
||||
uint32_t mask; \
|
||||
\
|
||||
mask = _pixman_image_get_solid ( \
|
||||
imp, mask_image, dest_image->bits.format); \
|
||||
\
|
||||
if ((flags & SKIP_ZERO_MASK) && mask == 0) \
|
||||
return; \
|
||||
\
|
||||
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
|
||||
dst_stride, dst_line, dst_cnt); \
|
||||
PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, src_type, \
|
||||
src_stride, src_line, src_cnt); \
|
||||
\
|
||||
while (height--) \
|
||||
{ \
|
||||
dst = dst_line; \
|
||||
dst_line += dst_stride; \
|
||||
src = src_line; \
|
||||
src_line += src_stride; \
|
||||
\
|
||||
pixman_composite_##name##_asm_mips (dst, src, mask, width); \
|
||||
} \
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
#define PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST(name, src_type, src_cnt, \
|
||||
mask_type, mask_cnt, \
|
||||
dst_type, dst_cnt) \
|
||||
void \
|
||||
pixman_composite_##name##_asm_mips (dst_type *dst, \
|
||||
src_type *src, \
|
||||
mask_type *mask, \
|
||||
int32_t w); \
|
||||
\
|
||||
static void \
|
||||
mips_composite_##name (pixman_implementation_t *imp, \
|
||||
pixman_composite_info_t *info) \
|
||||
{ \
|
||||
PIXMAN_COMPOSITE_ARGS (info); \
|
||||
dst_type *dst_line, *dst; \
|
||||
src_type *src_line, *src; \
|
||||
mask_type *mask_line, *mask; \
|
||||
int32_t dst_stride, src_stride, mask_stride; \
|
||||
\
|
||||
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
|
||||
dst_stride, dst_line, dst_cnt); \
|
||||
PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, src_type, \
|
||||
src_stride, src_line, src_cnt); \
|
||||
PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type, \
|
||||
mask_stride, mask_line, mask_cnt); \
|
||||
\
|
||||
while (height--) \
|
||||
{ \
|
||||
dst = dst_line; \
|
||||
dst_line += dst_stride; \
|
||||
mask = mask_line; \
|
||||
mask_line += mask_stride; \
|
||||
src = src_line; \
|
||||
src_line += src_stride; \
|
||||
pixman_composite_##name##_asm_mips (dst, src, mask, width); \
|
||||
} \
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define PIXMAN_MIPS_BIND_SCALED_NEAREST_SRC_A8_DST(flags, name, op, \
|
||||
src_type, dst_type) \
|
||||
void \
|
||||
pixman_scaled_nearest_scanline_##name##_##op##_asm_mips ( \
|
||||
dst_type * dst, \
|
||||
const src_type * src, \
|
||||
const uint8_t * mask, \
|
||||
int32_t w, \
|
||||
pixman_fixed_t vx, \
|
||||
pixman_fixed_t unit_x); \
|
||||
\
|
||||
static force_inline void \
|
||||
scaled_nearest_scanline_mips_##name##_##op (const uint8_t * mask, \
|
||||
dst_type * pd, \
|
||||
const src_type * ps, \
|
||||
int32_t w, \
|
||||
pixman_fixed_t vx, \
|
||||
pixman_fixed_t unit_x, \
|
||||
pixman_fixed_t max_vx, \
|
||||
pixman_bool_t zero_src) \
|
||||
{ \
|
||||
if ((flags & SKIP_ZERO_SRC) && zero_src) \
|
||||
return; \
|
||||
pixman_scaled_nearest_scanline_##name##_##op##_asm_mips (pd, ps, \
|
||||
mask, w, \
|
||||
vx, unit_x); \
|
||||
} \
|
||||
\
|
||||
FAST_NEAREST_MAINLOOP_COMMON (mips_##name##_cover_##op, \
|
||||
scaled_nearest_scanline_mips_##name##_##op, \
|
||||
src_type, uint8_t, dst_type, COVER, TRUE, FALSE)\
|
||||
FAST_NEAREST_MAINLOOP_COMMON (mips_##name##_none_##op, \
|
||||
scaled_nearest_scanline_mips_##name##_##op, \
|
||||
src_type, uint8_t, dst_type, NONE, TRUE, FALSE) \
|
||||
FAST_NEAREST_MAINLOOP_COMMON (mips_##name##_pad_##op, \
|
||||
scaled_nearest_scanline_mips_##name##_##op, \
|
||||
src_type, uint8_t, dst_type, PAD, TRUE, FALSE)
|
||||
|
||||
/* Provide entries for the fast path table */
|
||||
#define PIXMAN_MIPS_SIMPLE_NEAREST_A8_MASK_FAST_PATH(op,s,d,func) \
|
||||
SIMPLE_NEAREST_A8_MASK_FAST_PATH_COVER (op,s,d,func), \
|
||||
SIMPLE_NEAREST_A8_MASK_FAST_PATH_NONE (op,s,d,func), \
|
||||
SIMPLE_NEAREST_A8_MASK_FAST_PATH_PAD (op,s,d,func)
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#define PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST(flags, name, op, \
|
||||
src_type, dst_type) \
|
||||
void \
|
||||
pixman_scaled_bilinear_scanline_##name##_##op##_asm_mips( \
|
||||
dst_type * dst, \
|
||||
const src_type * src_top, \
|
||||
const src_type * src_bottom, \
|
||||
int32_t w, \
|
||||
int wt, \
|
||||
int wb, \
|
||||
pixman_fixed_t vx, \
|
||||
pixman_fixed_t unit_x); \
|
||||
static force_inline void \
|
||||
scaled_bilinear_scanline_mips_##name##_##op (dst_type * dst, \
|
||||
const uint32_t * mask, \
|
||||
const src_type * src_top, \
|
||||
const src_type * src_bottom, \
|
||||
int32_t w, \
|
||||
int wt, \
|
||||
int wb, \
|
||||
pixman_fixed_t vx, \
|
||||
pixman_fixed_t unit_x, \
|
||||
pixman_fixed_t max_vx, \
|
||||
pixman_bool_t zero_src) \
|
||||
{ \
|
||||
if ((flags & SKIP_ZERO_SRC) && zero_src) \
|
||||
return; \
|
||||
pixman_scaled_bilinear_scanline_##name##_##op##_asm_mips (dst, src_top, \
|
||||
src_bottom, w, \
|
||||
wt, wb, \
|
||||
vx, unit_x); \
|
||||
} \
|
||||
\
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_cover_##op, \
|
||||
scaled_bilinear_scanline_mips_##name##_##op, \
|
||||
src_type, uint32_t, dst_type, COVER, FLAG_NONE) \
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_none_##op, \
|
||||
scaled_bilinear_scanline_mips_##name##_##op, \
|
||||
src_type, uint32_t, dst_type, NONE, FLAG_NONE) \
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_pad_##op, \
|
||||
scaled_bilinear_scanline_mips_##name##_##op, \
|
||||
src_type, uint32_t, dst_type, PAD, FLAG_NONE) \
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_normal_##op, \
|
||||
scaled_bilinear_scanline_mips_##name##_##op, \
|
||||
src_type, uint32_t, dst_type, NORMAL, \
|
||||
FLAG_NONE)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST(flags, name, op, \
|
||||
src_type, dst_type) \
|
||||
void \
|
||||
pixman_scaled_bilinear_scanline_##name##_##op##_asm_mips ( \
|
||||
dst_type * dst, \
|
||||
const uint8_t * mask, \
|
||||
const src_type * top, \
|
||||
const src_type * bottom, \
|
||||
int wt, \
|
||||
int wb, \
|
||||
pixman_fixed_t x, \
|
||||
pixman_fixed_t ux, \
|
||||
int width); \
|
||||
\
|
||||
static force_inline void \
|
||||
scaled_bilinear_scanline_mips_##name##_##op (dst_type * dst, \
|
||||
const uint8_t * mask, \
|
||||
const src_type * src_top, \
|
||||
const src_type * src_bottom, \
|
||||
int32_t w, \
|
||||
int wt, \
|
||||
int wb, \
|
||||
pixman_fixed_t vx, \
|
||||
pixman_fixed_t unit_x, \
|
||||
pixman_fixed_t max_vx, \
|
||||
pixman_bool_t zero_src) \
|
||||
{ \
|
||||
if ((flags & SKIP_ZERO_SRC) && zero_src) \
|
||||
return; \
|
||||
pixman_scaled_bilinear_scanline_##name##_##op##_asm_mips ( \
|
||||
dst, mask, src_top, src_bottom, wt, wb, vx, unit_x, w); \
|
||||
} \
|
||||
\
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_cover_##op, \
|
||||
scaled_bilinear_scanline_mips_##name##_##op, \
|
||||
src_type, uint8_t, dst_type, COVER, \
|
||||
FLAG_HAVE_NON_SOLID_MASK) \
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_none_##op, \
|
||||
scaled_bilinear_scanline_mips_##name##_##op, \
|
||||
src_type, uint8_t, dst_type, NONE, \
|
||||
FLAG_HAVE_NON_SOLID_MASK) \
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_pad_##op, \
|
||||
scaled_bilinear_scanline_mips_##name##_##op, \
|
||||
src_type, uint8_t, dst_type, PAD, \
|
||||
FLAG_HAVE_NON_SOLID_MASK) \
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_normal_##op, \
|
||||
scaled_bilinear_scanline_mips_##name##_##op, \
|
||||
src_type, uint8_t, dst_type, NORMAL, \
|
||||
FLAG_HAVE_NON_SOLID_MASK)
|
||||
|
||||
#endif //PIXMAN_MIPS_DSPR2_H
|
||||
382
gfx/cairo/libpixman/src/pixman-mips-memcpy-asm.S
Normal file
382
gfx/cairo/libpixman/src/pixman-mips-memcpy-asm.S
Normal file
|
|
@ -0,0 +1,382 @@
|
|||
/*
|
||||
* Copyright (c) 2012
|
||||
* MIPS Technologies, Inc., California.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the MIPS Technologies, Inc., nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "pixman-mips-dspr2-asm.h"
|
||||
|
||||
/*
|
||||
* This routine could be optimized for MIPS64. The current code only
|
||||
* uses MIPS32 instructions.
|
||||
*/
|
||||
|
||||
#ifdef EB
|
||||
# define LWHI lwl /* high part is left in big-endian */
|
||||
# define SWHI swl /* high part is left in big-endian */
|
||||
# define LWLO lwr /* low part is right in big-endian */
|
||||
# define SWLO swr /* low part is right in big-endian */
|
||||
#else
|
||||
# define LWHI lwr /* high part is right in little-endian */
|
||||
# define SWHI swr /* high part is right in little-endian */
|
||||
# define LWLO lwl /* low part is left in big-endian */
|
||||
# define SWLO swl /* low part is left in big-endian */
|
||||
#endif
|
||||
|
||||
LEAF_MIPS32R2(pixman_mips_fast_memcpy)
|
||||
|
||||
slti AT, a2, 8
|
||||
bne AT, zero, $last8
|
||||
move v0, a0 /* memcpy returns the dst pointer */
|
||||
|
||||
/* Test if the src and dst are word-aligned, or can be made word-aligned */
|
||||
xor t8, a1, a0
|
||||
andi t8, t8, 0x3 /* t8 is a0/a1 word-displacement */
|
||||
|
||||
bne t8, zero, $unaligned
|
||||
negu a3, a0
|
||||
|
||||
andi a3, a3, 0x3 /* we need to copy a3 bytes to make a0/a1 aligned */
|
||||
beq a3, zero, $chk16w /* when a3=0 then the dst (a0) is word-aligned */
|
||||
subu a2, a2, a3 /* now a2 is the remining bytes count */
|
||||
|
||||
LWHI t8, 0(a1)
|
||||
addu a1, a1, a3
|
||||
SWHI t8, 0(a0)
|
||||
addu a0, a0, a3
|
||||
|
||||
/* Now the dst/src are mutually word-aligned with word-aligned addresses */
|
||||
$chk16w: andi t8, a2, 0x3f /* any whole 64-byte chunks? */
|
||||
/* t8 is the byte count after 64-byte chunks */
|
||||
|
||||
beq a2, t8, $chk8w /* if a2==t8, no 64-byte chunks */
|
||||
/* There will be at most 1 32-byte chunk after it */
|
||||
subu a3, a2, t8 /* subtract from a2 the reminder */
|
||||
/* Here a3 counts bytes in 16w chunks */
|
||||
addu a3, a0, a3 /* Now a3 is the final dst after 64-byte chunks */
|
||||
|
||||
addu t0, a0, a2 /* t0 is the "past the end" address */
|
||||
|
||||
/*
|
||||
* When in the loop we exercise "pref 30, x(a0)", the a0+x should not be past
|
||||
* the "t0-32" address
|
||||
* This means: for x=128 the last "safe" a0 address is "t0-160"
|
||||
* Alternatively, for x=64 the last "safe" a0 address is "t0-96"
|
||||
* In the current version we use "pref 30, 128(a0)", so "t0-160" is the limit
|
||||
*/
|
||||
subu t9, t0, 160 /* t9 is the "last safe pref 30, 128(a0)" address */
|
||||
|
||||
pref 0, 0(a1) /* bring the first line of src, addr 0 */
|
||||
pref 0, 32(a1) /* bring the second line of src, addr 32 */
|
||||
pref 0, 64(a1) /* bring the third line of src, addr 64 */
|
||||
pref 30, 32(a0) /* safe, as we have at least 64 bytes ahead */
|
||||
/* In case the a0 > t9 don't use "pref 30" at all */
|
||||
sgtu v1, a0, t9
|
||||
bgtz v1, $loop16w /* skip "pref 30, 64(a0)" for too short arrays */
|
||||
nop
|
||||
/* otherwise, start with using pref30 */
|
||||
pref 30, 64(a0)
|
||||
$loop16w:
|
||||
pref 0, 96(a1)
|
||||
lw t0, 0(a1)
|
||||
bgtz v1, $skip_pref30_96 /* skip "pref 30, 96(a0)" */
|
||||
lw t1, 4(a1)
|
||||
pref 30, 96(a0) /* continue setting up the dest, addr 96 */
|
||||
$skip_pref30_96:
|
||||
lw t2, 8(a1)
|
||||
lw t3, 12(a1)
|
||||
lw t4, 16(a1)
|
||||
lw t5, 20(a1)
|
||||
lw t6, 24(a1)
|
||||
lw t7, 28(a1)
|
||||
pref 0, 128(a1) /* bring the next lines of src, addr 128 */
|
||||
|
||||
sw t0, 0(a0)
|
||||
sw t1, 4(a0)
|
||||
sw t2, 8(a0)
|
||||
sw t3, 12(a0)
|
||||
sw t4, 16(a0)
|
||||
sw t5, 20(a0)
|
||||
sw t6, 24(a0)
|
||||
sw t7, 28(a0)
|
||||
|
||||
lw t0, 32(a1)
|
||||
bgtz v1, $skip_pref30_128 /* skip "pref 30, 128(a0)" */
|
||||
lw t1, 36(a1)
|
||||
pref 30, 128(a0) /* continue setting up the dest, addr 128 */
|
||||
$skip_pref30_128:
|
||||
lw t2, 40(a1)
|
||||
lw t3, 44(a1)
|
||||
lw t4, 48(a1)
|
||||
lw t5, 52(a1)
|
||||
lw t6, 56(a1)
|
||||
lw t7, 60(a1)
|
||||
pref 0, 160(a1) /* bring the next lines of src, addr 160 */
|
||||
|
||||
sw t0, 32(a0)
|
||||
sw t1, 36(a0)
|
||||
sw t2, 40(a0)
|
||||
sw t3, 44(a0)
|
||||
sw t4, 48(a0)
|
||||
sw t5, 52(a0)
|
||||
sw t6, 56(a0)
|
||||
sw t7, 60(a0)
|
||||
|
||||
addiu a0, a0, 64 /* adding 64 to dest */
|
||||
sgtu v1, a0, t9
|
||||
bne a0, a3, $loop16w
|
||||
addiu a1, a1, 64 /* adding 64 to src */
|
||||
move a2, t8
|
||||
|
||||
/* Here we have src and dest word-aligned but less than 64-bytes to go */
|
||||
|
||||
$chk8w:
|
||||
pref 0, 0x0(a1)
|
||||
andi t8, a2, 0x1f /* is there a 32-byte chunk? */
|
||||
/* the t8 is the reminder count past 32-bytes */
|
||||
beq a2, t8, $chk1w /* when a2=t8, no 32-byte chunk */
|
||||
nop
|
||||
|
||||
lw t0, 0(a1)
|
||||
lw t1, 4(a1)
|
||||
lw t2, 8(a1)
|
||||
lw t3, 12(a1)
|
||||
lw t4, 16(a1)
|
||||
lw t5, 20(a1)
|
||||
lw t6, 24(a1)
|
||||
lw t7, 28(a1)
|
||||
addiu a1, a1, 32
|
||||
|
||||
sw t0, 0(a0)
|
||||
sw t1, 4(a0)
|
||||
sw t2, 8(a0)
|
||||
sw t3, 12(a0)
|
||||
sw t4, 16(a0)
|
||||
sw t5, 20(a0)
|
||||
sw t6, 24(a0)
|
||||
sw t7, 28(a0)
|
||||
addiu a0, a0, 32
|
||||
|
||||
$chk1w:
|
||||
andi a2, t8, 0x3 /* now a2 is the reminder past 1w chunks */
|
||||
beq a2, t8, $last8
|
||||
subu a3, t8, a2 /* a3 is count of bytes in 1w chunks */
|
||||
addu a3, a0, a3 /* now a3 is the dst address past the 1w chunks */
|
||||
|
||||
/* copying in words (4-byte chunks) */
|
||||
$wordCopy_loop:
|
||||
lw t3, 0(a1) /* the first t3 may be equal t0 ... optimize? */
|
||||
addiu a1, a1, 4
|
||||
addiu a0, a0, 4
|
||||
bne a0, a3, $wordCopy_loop
|
||||
sw t3, -4(a0)
|
||||
|
||||
/* For the last (<8) bytes */
|
||||
$last8:
|
||||
blez a2, leave
|
||||
addu a3, a0, a2 /* a3 is the last dst address */
|
||||
$last8loop:
|
||||
lb v1, 0(a1)
|
||||
addiu a1, a1, 1
|
||||
addiu a0, a0, 1
|
||||
bne a0, a3, $last8loop
|
||||
sb v1, -1(a0)
|
||||
|
||||
leave: j ra
|
||||
nop
|
||||
|
||||
/*
|
||||
* UNALIGNED case
|
||||
*/
|
||||
|
||||
$unaligned:
|
||||
/* got here with a3="negu a0" */
|
||||
andi a3, a3, 0x3 /* test if the a0 is word aligned */
|
||||
beqz a3, $ua_chk16w
|
||||
subu a2, a2, a3 /* bytes left after initial a3 bytes */
|
||||
|
||||
LWHI v1, 0(a1)
|
||||
LWLO v1, 3(a1)
|
||||
addu a1, a1, a3 /* a3 may be here 1, 2 or 3 */
|
||||
SWHI v1, 0(a0)
|
||||
addu a0, a0, a3 /* below the dst will be word aligned (NOTE1) */
|
||||
|
||||
$ua_chk16w: andi t8, a2, 0x3f /* any whole 64-byte chunks? */
|
||||
/* t8 is the byte count after 64-byte chunks */
|
||||
beq a2, t8, $ua_chk8w /* if a2==t8, no 64-byte chunks */
|
||||
/* There will be at most 1 32-byte chunk after it */
|
||||
subu a3, a2, t8 /* subtract from a2 the reminder */
|
||||
/* Here a3 counts bytes in 16w chunks */
|
||||
addu a3, a0, a3 /* Now a3 is the final dst after 64-byte chunks */
|
||||
|
||||
addu t0, a0, a2 /* t0 is the "past the end" address */
|
||||
|
||||
subu t9, t0, 160 /* t9 is the "last safe pref 30, 128(a0)" address */
|
||||
|
||||
pref 0, 0(a1) /* bring the first line of src, addr 0 */
|
||||
pref 0, 32(a1) /* bring the second line of src, addr 32 */
|
||||
pref 0, 64(a1) /* bring the third line of src, addr 64 */
|
||||
pref 30, 32(a0) /* safe, as we have at least 64 bytes ahead */
|
||||
/* In case the a0 > t9 don't use "pref 30" at all */
|
||||
sgtu v1, a0, t9
|
||||
bgtz v1, $ua_loop16w /* skip "pref 30, 64(a0)" for too short arrays */
|
||||
nop
|
||||
/* otherwise, start with using pref30 */
|
||||
pref 30, 64(a0)
|
||||
$ua_loop16w:
|
||||
pref 0, 96(a1)
|
||||
LWHI t0, 0(a1)
|
||||
LWLO t0, 3(a1)
|
||||
LWHI t1, 4(a1)
|
||||
bgtz v1, $ua_skip_pref30_96
|
||||
LWLO t1, 7(a1)
|
||||
pref 30, 96(a0) /* continue setting up the dest, addr 96 */
|
||||
$ua_skip_pref30_96:
|
||||
LWHI t2, 8(a1)
|
||||
LWLO t2, 11(a1)
|
||||
LWHI t3, 12(a1)
|
||||
LWLO t3, 15(a1)
|
||||
LWHI t4, 16(a1)
|
||||
LWLO t4, 19(a1)
|
||||
LWHI t5, 20(a1)
|
||||
LWLO t5, 23(a1)
|
||||
LWHI t6, 24(a1)
|
||||
LWLO t6, 27(a1)
|
||||
LWHI t7, 28(a1)
|
||||
LWLO t7, 31(a1)
|
||||
pref 0, 128(a1) /* bring the next lines of src, addr 128 */
|
||||
|
||||
sw t0, 0(a0)
|
||||
sw t1, 4(a0)
|
||||
sw t2, 8(a0)
|
||||
sw t3, 12(a0)
|
||||
sw t4, 16(a0)
|
||||
sw t5, 20(a0)
|
||||
sw t6, 24(a0)
|
||||
sw t7, 28(a0)
|
||||
|
||||
LWHI t0, 32(a1)
|
||||
LWLO t0, 35(a1)
|
||||
LWHI t1, 36(a1)
|
||||
bgtz v1, $ua_skip_pref30_128
|
||||
LWLO t1, 39(a1)
|
||||
pref 30, 128(a0) /* continue setting up the dest, addr 128 */
|
||||
$ua_skip_pref30_128:
|
||||
LWHI t2, 40(a1)
|
||||
LWLO t2, 43(a1)
|
||||
LWHI t3, 44(a1)
|
||||
LWLO t3, 47(a1)
|
||||
LWHI t4, 48(a1)
|
||||
LWLO t4, 51(a1)
|
||||
LWHI t5, 52(a1)
|
||||
LWLO t5, 55(a1)
|
||||
LWHI t6, 56(a1)
|
||||
LWLO t6, 59(a1)
|
||||
LWHI t7, 60(a1)
|
||||
LWLO t7, 63(a1)
|
||||
pref 0, 160(a1) /* bring the next lines of src, addr 160 */
|
||||
|
||||
sw t0, 32(a0)
|
||||
sw t1, 36(a0)
|
||||
sw t2, 40(a0)
|
||||
sw t3, 44(a0)
|
||||
sw t4, 48(a0)
|
||||
sw t5, 52(a0)
|
||||
sw t6, 56(a0)
|
||||
sw t7, 60(a0)
|
||||
|
||||
addiu a0, a0, 64 /* adding 64 to dest */
|
||||
sgtu v1, a0, t9
|
||||
bne a0, a3, $ua_loop16w
|
||||
addiu a1, a1, 64 /* adding 64 to src */
|
||||
move a2, t8
|
||||
|
||||
/* Here we have src and dest word-aligned but less than 64-bytes to go */
|
||||
|
||||
$ua_chk8w:
|
||||
pref 0, 0x0(a1)
|
||||
andi t8, a2, 0x1f /* is there a 32-byte chunk? */
|
||||
/* the t8 is the reminder count */
|
||||
beq a2, t8, $ua_chk1w /* when a2=t8, no 32-byte chunk */
|
||||
|
||||
LWHI t0, 0(a1)
|
||||
LWLO t0, 3(a1)
|
||||
LWHI t1, 4(a1)
|
||||
LWLO t1, 7(a1)
|
||||
LWHI t2, 8(a1)
|
||||
LWLO t2, 11(a1)
|
||||
LWHI t3, 12(a1)
|
||||
LWLO t3, 15(a1)
|
||||
LWHI t4, 16(a1)
|
||||
LWLO t4, 19(a1)
|
||||
LWHI t5, 20(a1)
|
||||
LWLO t5, 23(a1)
|
||||
LWHI t6, 24(a1)
|
||||
LWLO t6, 27(a1)
|
||||
LWHI t7, 28(a1)
|
||||
LWLO t7, 31(a1)
|
||||
addiu a1, a1, 32
|
||||
|
||||
sw t0, 0(a0)
|
||||
sw t1, 4(a0)
|
||||
sw t2, 8(a0)
|
||||
sw t3, 12(a0)
|
||||
sw t4, 16(a0)
|
||||
sw t5, 20(a0)
|
||||
sw t6, 24(a0)
|
||||
sw t7, 28(a0)
|
||||
addiu a0, a0, 32
|
||||
|
||||
$ua_chk1w:
|
||||
andi a2, t8, 0x3 /* now a2 is the reminder past 1w chunks */
|
||||
beq a2, t8, $ua_smallCopy
|
||||
subu a3, t8, a2 /* a3 is count of bytes in 1w chunks */
|
||||
addu a3, a0, a3 /* now a3 is the dst address past the 1w chunks */
|
||||
|
||||
/* copying in words (4-byte chunks) */
|
||||
$ua_wordCopy_loop:
|
||||
LWHI v1, 0(a1)
|
||||
LWLO v1, 3(a1)
|
||||
addiu a1, a1, 4
|
||||
addiu a0, a0, 4 /* note: dst=a0 is word aligned here, see NOTE1 */
|
||||
bne a0, a3, $ua_wordCopy_loop
|
||||
sw v1, -4(a0)
|
||||
|
||||
/* Now less than 4 bytes (value in a2) left to copy */
|
||||
$ua_smallCopy:
|
||||
beqz a2, leave
|
||||
addu a3, a0, a2 /* a3 is the last dst address */
|
||||
$ua_smallCopy_loop:
|
||||
lb v1, 0(a1)
|
||||
addiu a1, a1, 1
|
||||
addiu a0, a0, 1
|
||||
bne a0, a3, $ua_smallCopy_loop
|
||||
sb v1, -1(a0)
|
||||
|
||||
j ra
|
||||
nop
|
||||
|
||||
END(pixman_mips_fast_memcpy)
|
||||
94
gfx/cairo/libpixman/src/pixman-mips.c
Normal file
94
gfx/cairo/libpixman/src/pixman-mips.c
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright © 2000 SuSE, Inc.
|
||||
* Copyright © 2007 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of SuSE not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. SuSE makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
|
||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "pixman-private.h"
|
||||
|
||||
#if defined(USE_MIPS_DSPR2) || defined(USE_LOONGSON_MMI)
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static pixman_bool_t
|
||||
have_feature (const char *search_string)
|
||||
{
|
||||
#if defined (__linux__) /* linux ELF */
|
||||
/* Simple detection of MIPS features at runtime for Linux.
|
||||
* It is based on /proc/cpuinfo, which reveals hardware configuration
|
||||
* to user-space applications. According to MIPS (early 2010), no similar
|
||||
* facility is universally available on the MIPS architectures, so it's up
|
||||
* to individual OSes to provide such.
|
||||
*/
|
||||
const char *file_name = "/proc/cpuinfo";
|
||||
char cpuinfo_line[256];
|
||||
FILE *f = NULL;
|
||||
|
||||
if ((f = fopen (file_name, "r")) == NULL)
|
||||
return FALSE;
|
||||
|
||||
while (fgets (cpuinfo_line, sizeof (cpuinfo_line), f) != NULL)
|
||||
{
|
||||
if (strstr (cpuinfo_line, search_string) != NULL)
|
||||
{
|
||||
fclose (f);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
fclose (f);
|
||||
#endif
|
||||
|
||||
/* Did not find string in the proc file, or not Linux ELF. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
pixman_implementation_t *
|
||||
_pixman_mips_get_implementations (pixman_implementation_t *imp)
|
||||
{
|
||||
#ifdef USE_LOONGSON_MMI
|
||||
/* I really don't know if some Loongson CPUs don't have MMI. */
|
||||
if (!_pixman_disabled ("loongson-mmi") && have_feature ("Loongson"))
|
||||
imp = _pixman_implementation_create_mmx (imp);
|
||||
#endif
|
||||
|
||||
#ifdef USE_MIPS_DSPR2
|
||||
if (!_pixman_disabled ("mips-dspr2"))
|
||||
{
|
||||
int already_compiling_everything_for_dspr2 = 0;
|
||||
#if defined(__mips_dsp) && (__mips_dsp_rev >= 2)
|
||||
already_compiling_everything_for_dspr2 = 1;
|
||||
#endif
|
||||
if (already_compiling_everything_for_dspr2 ||
|
||||
/* Only currently available MIPS core that supports DSPr2 is 74K. */
|
||||
have_feature ("MIPS 74K"))
|
||||
{
|
||||
imp = _pixman_implementation_create_mips_dspr2 (imp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return imp;
|
||||
}
|
||||
4084
gfx/cairo/libpixman/src/pixman-mmx.c
Normal file
4084
gfx/cairo/libpixman/src/pixman-mmx.c
Normal file
File diff suppressed because it is too large
Load diff
176
gfx/cairo/libpixman/src/pixman-noop.c
Normal file
176
gfx/cairo/libpixman/src/pixman-noop.c
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
|
||||
/*
|
||||
* Copyright © 2011 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "pixman-private.h"
|
||||
#include "pixman-combine32.h"
|
||||
#include "pixman-inlines.h"
|
||||
|
||||
static void
|
||||
noop_composite (pixman_implementation_t *imp,
|
||||
pixman_composite_info_t *info)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
dest_write_back_direct (pixman_iter_t *iter)
|
||||
{
|
||||
iter->buffer += iter->image->bits.rowstride;
|
||||
}
|
||||
|
||||
static uint32_t *
|
||||
noop_get_scanline (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
uint32_t *result = iter->buffer;
|
||||
|
||||
iter->buffer += iter->image->bits.rowstride;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint32_t *
|
||||
get_scanline_null (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static pixman_bool_t
|
||||
noop_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
|
||||
{
|
||||
pixman_image_t *image = iter->image;
|
||||
|
||||
#define FLAGS \
|
||||
(FAST_PATH_STANDARD_FLAGS | FAST_PATH_ID_TRANSFORM)
|
||||
|
||||
if (!image)
|
||||
{
|
||||
iter->get_scanline = get_scanline_null;
|
||||
}
|
||||
else if ((iter->iter_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) ==
|
||||
(ITER_IGNORE_ALPHA | ITER_IGNORE_RGB))
|
||||
{
|
||||
iter->get_scanline = _pixman_iter_get_scanline_noop;
|
||||
}
|
||||
else if (image->common.extended_format_code == PIXMAN_solid &&
|
||||
(iter->image->type == SOLID ||
|
||||
(iter->image_flags & FAST_PATH_NO_ALPHA_MAP)))
|
||||
{
|
||||
if (iter->iter_flags & ITER_NARROW)
|
||||
{
|
||||
uint32_t *buffer = iter->buffer;
|
||||
uint32_t *end = buffer + iter->width;
|
||||
uint32_t color;
|
||||
|
||||
if (image->type == SOLID)
|
||||
color = image->solid.color_32;
|
||||
else
|
||||
color = image->bits.fetch_pixel_32 (&image->bits, 0, 0);
|
||||
|
||||
while (buffer < end)
|
||||
*(buffer++) = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
argb_t *buffer = (argb_t *)iter->buffer;
|
||||
argb_t *end = buffer + iter->width;
|
||||
argb_t color;
|
||||
|
||||
if (image->type == SOLID)
|
||||
color = image->solid.color_float;
|
||||
else
|
||||
color = image->bits.fetch_pixel_float (&image->bits, 0, 0);
|
||||
|
||||
while (buffer < end)
|
||||
*(buffer++) = color;
|
||||
}
|
||||
|
||||
iter->get_scanline = _pixman_iter_get_scanline_noop;
|
||||
}
|
||||
else if (image->common.extended_format_code == PIXMAN_a8r8g8b8 &&
|
||||
(iter->iter_flags & ITER_NARROW) &&
|
||||
(iter->image_flags & FLAGS) == FLAGS &&
|
||||
iter->x >= 0 && iter->y >= 0 &&
|
||||
iter->x + iter->width <= image->bits.width &&
|
||||
iter->y + iter->height <= image->bits.height)
|
||||
{
|
||||
iter->buffer =
|
||||
image->bits.bits + iter->y * image->bits.rowstride + iter->x;
|
||||
|
||||
iter->get_scanline = noop_get_scanline;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static pixman_bool_t
|
||||
noop_dest_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
|
||||
{
|
||||
pixman_image_t *image = iter->image;
|
||||
uint32_t image_flags = iter->image_flags;
|
||||
uint32_t iter_flags = iter->iter_flags;
|
||||
|
||||
if ((image_flags & FAST_PATH_STD_DEST_FLAGS) == FAST_PATH_STD_DEST_FLAGS &&
|
||||
(iter_flags & ITER_NARROW) == ITER_NARROW &&
|
||||
((image->common.extended_format_code == PIXMAN_a8r8g8b8) ||
|
||||
(image->common.extended_format_code == PIXMAN_x8r8g8b8 &&
|
||||
(iter_flags & (ITER_LOCALIZED_ALPHA)))))
|
||||
{
|
||||
iter->buffer = image->bits.bits + iter->y * image->bits.rowstride + iter->x;
|
||||
|
||||
iter->get_scanline = _pixman_iter_get_scanline_noop;
|
||||
iter->write_back = dest_write_back_direct;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static const pixman_fast_path_t noop_fast_paths[] =
|
||||
{
|
||||
{ PIXMAN_OP_DST, PIXMAN_any, 0, PIXMAN_any, 0, PIXMAN_any, 0, noop_composite },
|
||||
{ PIXMAN_OP_NONE },
|
||||
};
|
||||
|
||||
pixman_implementation_t *
|
||||
_pixman_implementation_create_noop (pixman_implementation_t *fallback)
|
||||
{
|
||||
pixman_implementation_t *imp =
|
||||
_pixman_implementation_create (fallback, noop_fast_paths);
|
||||
|
||||
imp->src_iter_init = noop_src_iter_init;
|
||||
imp->dest_iter_init = noop_dest_iter_init;
|
||||
|
||||
return imp;
|
||||
}
|
||||
155
gfx/cairo/libpixman/src/pixman-ppc.c
Normal file
155
gfx/cairo/libpixman/src/pixman-ppc.c
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* Copyright © 2000 SuSE, Inc.
|
||||
* Copyright © 2007 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of SuSE not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. SuSE makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
|
||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "pixman-private.h"
|
||||
|
||||
#ifdef USE_VMX
|
||||
|
||||
/* The CPU detection code needs to be in a file not compiled with
|
||||
* "-maltivec -mabi=altivec", as gcc would try to save vector register
|
||||
* across function calls causing SIGILL on cpus without Altivec/vmx.
|
||||
*/
|
||||
#ifdef __APPLE__
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
static pixman_bool_t
|
||||
pixman_have_vmx (void)
|
||||
{
|
||||
int error, have_vmx;
|
||||
size_t length = sizeof(have_vmx);
|
||||
|
||||
error = sysctlbyname ("hw.optional.altivec", &have_vmx, &length, NULL, 0);
|
||||
|
||||
if (error)
|
||||
return FALSE;
|
||||
|
||||
return have_vmx;
|
||||
}
|
||||
|
||||
#elif defined (__OpenBSD__)
|
||||
#include <sys/param.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <machine/cpu.h>
|
||||
|
||||
static pixman_bool_t
|
||||
pixman_have_vmx (void)
|
||||
{
|
||||
int error, have_vmx;
|
||||
int mib[2] = { CTL_MACHDEP, CPU_ALTIVEC };
|
||||
size_t length = sizeof(have_vmx);
|
||||
|
||||
error = sysctl (mib, 2, &have_vmx, &length, NULL, 0);
|
||||
|
||||
if (error != 0)
|
||||
return FALSE;
|
||||
|
||||
return have_vmx;
|
||||
}
|
||||
|
||||
#elif defined (__linux__)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <linux/auxvec.h>
|
||||
#include <asm/cputable.h>
|
||||
|
||||
static pixman_bool_t
|
||||
pixman_have_vmx (void)
|
||||
{
|
||||
int have_vmx = FALSE;
|
||||
int fd;
|
||||
struct
|
||||
{
|
||||
unsigned long type;
|
||||
unsigned long value;
|
||||
} aux;
|
||||
|
||||
fd = open ("/proc/self/auxv", O_RDONLY);
|
||||
if (fd >= 0)
|
||||
{
|
||||
while (read (fd, &aux, sizeof (aux)) == sizeof (aux))
|
||||
{
|
||||
if (aux.type == AT_HWCAP && (aux.value & PPC_FEATURE_HAS_ALTIVEC))
|
||||
{
|
||||
have_vmx = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
close (fd);
|
||||
}
|
||||
|
||||
return have_vmx;
|
||||
}
|
||||
|
||||
#else /* !__APPLE__ && !__OpenBSD__ && !__linux__ */
|
||||
#include <signal.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
static jmp_buf jump_env;
|
||||
|
||||
static void
|
||||
vmx_test (int sig,
|
||||
siginfo_t *si,
|
||||
void * unused)
|
||||
{
|
||||
longjmp (jump_env, 1);
|
||||
}
|
||||
|
||||
static pixman_bool_t
|
||||
pixman_have_vmx (void)
|
||||
{
|
||||
struct sigaction sa, osa;
|
||||
int jmp_result;
|
||||
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
sigemptyset (&sa.sa_mask);
|
||||
sa.sa_sigaction = vmx_test;
|
||||
sigaction (SIGILL, &sa, &osa);
|
||||
jmp_result = setjmp (jump_env);
|
||||
if (jmp_result == 0)
|
||||
{
|
||||
asm volatile ( "vor 0, 0, 0" );
|
||||
}
|
||||
sigaction (SIGILL, &osa, NULL);
|
||||
return (jmp_result == 0);
|
||||
}
|
||||
|
||||
#endif /* __APPLE__ */
|
||||
#endif /* USE_VMX */
|
||||
|
||||
pixman_implementation_t *
|
||||
_pixman_ppc_get_implementations (pixman_implementation_t *imp)
|
||||
{
|
||||
#ifdef USE_VMX
|
||||
if (!_pixman_disabled ("vmx") && pixman_have_vmx ())
|
||||
imp = _pixman_implementation_create_vmx (imp);
|
||||
#endif
|
||||
|
||||
return imp;
|
||||
}
|
||||
1187
gfx/cairo/libpixman/src/pixman-private.h
Normal file
1187
gfx/cairo/libpixman/src/pixman-private.h
Normal file
File diff suppressed because it is too large
Load diff
727
gfx/cairo/libpixman/src/pixman-radial-gradient.c
Normal file
727
gfx/cairo/libpixman/src/pixman-radial-gradient.c
Normal file
|
|
@ -0,0 +1,727 @@
|
|||
/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
|
||||
/*
|
||||
*
|
||||
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
|
||||
* Copyright © 2000 SuSE, Inc.
|
||||
* 2005 Lars Knoll & Zack Rusin, Trolltech
|
||||
* Copyright © 2007 Red Hat, Inc.
|
||||
*
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "pixman-private.h"
|
||||
|
||||
#include "pixman-dither.h"
|
||||
|
||||
static inline pixman_fixed_32_32_t
|
||||
dot (pixman_fixed_48_16_t x1,
|
||||
pixman_fixed_48_16_t y1,
|
||||
pixman_fixed_48_16_t z1,
|
||||
pixman_fixed_48_16_t x2,
|
||||
pixman_fixed_48_16_t y2,
|
||||
pixman_fixed_48_16_t z2)
|
||||
{
|
||||
/*
|
||||
* Exact computation, assuming that the input values can
|
||||
* be represented as pixman_fixed_16_16_t
|
||||
*/
|
||||
return x1 * x2 + y1 * y2 + z1 * z2;
|
||||
}
|
||||
|
||||
static inline double
|
||||
fdot (double x1,
|
||||
double y1,
|
||||
double z1,
|
||||
double x2,
|
||||
double y2,
|
||||
double z2)
|
||||
{
|
||||
/*
|
||||
* Error can be unbound in some special cases.
|
||||
* Using clever dot product algorithms (for example compensated
|
||||
* dot product) would improve this but make the code much less
|
||||
* obvious
|
||||
*/
|
||||
return x1 * x2 + y1 * y2 + z1 * z2;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
radial_compute_color (double a,
|
||||
double b,
|
||||
double c,
|
||||
double inva,
|
||||
double dr,
|
||||
double mindr,
|
||||
pixman_gradient_walker_t *walker,
|
||||
pixman_repeat_t repeat)
|
||||
{
|
||||
/*
|
||||
* In this function error propagation can lead to bad results:
|
||||
* - discr can have an unbound error (if b*b-a*c is very small),
|
||||
* potentially making it the opposite sign of what it should have been
|
||||
* (thus clearing a pixel that would have been colored or vice-versa)
|
||||
* or propagating the error to sqrtdiscr;
|
||||
* if discr has the wrong sign or b is very small, this can lead to bad
|
||||
* results
|
||||
*
|
||||
* - the algorithm used to compute the solutions of the quadratic
|
||||
* equation is not numerically stable (but saves one division compared
|
||||
* to the numerically stable one);
|
||||
* this can be a problem if a*c is much smaller than b*b
|
||||
*
|
||||
* - the above problems are worse if a is small (as inva becomes bigger)
|
||||
*/
|
||||
double discr;
|
||||
|
||||
if (a == 0)
|
||||
{
|
||||
double t;
|
||||
|
||||
if (b == 0)
|
||||
return 0;
|
||||
|
||||
t = pixman_fixed_1 / 2 * c / b;
|
||||
if (repeat == PIXMAN_REPEAT_NONE)
|
||||
{
|
||||
if (0 <= t && t <= pixman_fixed_1)
|
||||
return _pixman_gradient_walker_pixel (walker, t);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t * dr >= mindr)
|
||||
return _pixman_gradient_walker_pixel (walker, t);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
discr = fdot (b, a, 0, b, -c, 0);
|
||||
if (discr >= 0)
|
||||
{
|
||||
double sqrtdiscr, t0, t1;
|
||||
|
||||
sqrtdiscr = sqrt (discr);
|
||||
t0 = (b + sqrtdiscr) * inva;
|
||||
t1 = (b - sqrtdiscr) * inva;
|
||||
|
||||
/*
|
||||
* The root that must be used is the biggest one that belongs
|
||||
* to the valid range ([0,1] for PIXMAN_REPEAT_NONE, any
|
||||
* solution that results in a positive radius otherwise).
|
||||
*
|
||||
* If a > 0, t0 is the biggest solution, so if it is valid, it
|
||||
* is the correct result.
|
||||
*
|
||||
* If a < 0, only one of the solutions can be valid, so the
|
||||
* order in which they are tested is not important.
|
||||
*/
|
||||
if (repeat == PIXMAN_REPEAT_NONE)
|
||||
{
|
||||
if (0 <= t0 && t0 <= pixman_fixed_1)
|
||||
return _pixman_gradient_walker_pixel (walker, t0);
|
||||
else if (0 <= t1 && t1 <= pixman_fixed_1)
|
||||
return _pixman_gradient_walker_pixel (walker, t1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t0 * dr >= mindr)
|
||||
return _pixman_gradient_walker_pixel (walker, t0);
|
||||
else if (t1 * dr >= mindr)
|
||||
return _pixman_gradient_walker_pixel (walker, t1);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t *
|
||||
radial_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
/*
|
||||
* Implementation of radial gradients following the PDF specification.
|
||||
* See section 8.7.4.5.4 Type 3 (Radial) Shadings of the PDF Reference
|
||||
* Manual (PDF 32000-1:2008 at the time of this writing).
|
||||
*
|
||||
* In the radial gradient problem we are given two circles (c₁,r₁) and
|
||||
* (c₂,r₂) that define the gradient itself.
|
||||
*
|
||||
* Mathematically the gradient can be defined as the family of circles
|
||||
*
|
||||
* ((1-t)·c₁ + t·(c₂), (1-t)·r₁ + t·r₂)
|
||||
*
|
||||
* excluding those circles whose radius would be < 0. When a point
|
||||
* belongs to more than one circle, the one with a bigger t is the only
|
||||
* one that contributes to its color. When a point does not belong
|
||||
* to any of the circles, it is transparent black, i.e. RGBA (0, 0, 0, 0).
|
||||
* Further limitations on the range of values for t are imposed when
|
||||
* the gradient is not repeated, namely t must belong to [0,1].
|
||||
*
|
||||
* The graphical result is the same as drawing the valid (radius > 0)
|
||||
* circles with increasing t in [-inf, +inf] (or in [0,1] if the gradient
|
||||
* is not repeated) using SOURCE operator composition.
|
||||
*
|
||||
* It looks like a cone pointing towards the viewer if the ending circle
|
||||
* is smaller than the starting one, a cone pointing inside the page if
|
||||
* the starting circle is the smaller one and like a cylinder if they
|
||||
* have the same radius.
|
||||
*
|
||||
* What we actually do is, given the point whose color we are interested
|
||||
* in, compute the t values for that point, solving for t in:
|
||||
*
|
||||
* length((1-t)·c₁ + t·(c₂) - p) = (1-t)·r₁ + t·r₂
|
||||
*
|
||||
* Let's rewrite it in a simpler way, by defining some auxiliary
|
||||
* variables:
|
||||
*
|
||||
* cd = c₂ - c₁
|
||||
* pd = p - c₁
|
||||
* dr = r₂ - r₁
|
||||
* length(t·cd - pd) = r₁ + t·dr
|
||||
*
|
||||
* which actually means
|
||||
*
|
||||
* hypot(t·cdx - pdx, t·cdy - pdy) = r₁ + t·dr
|
||||
*
|
||||
* or
|
||||
*
|
||||
* ⎷((t·cdx - pdx)² + (t·cdy - pdy)²) = r₁ + t·dr.
|
||||
*
|
||||
* If we impose (as stated earlier) that r₁ + t·dr >= 0, it becomes:
|
||||
*
|
||||
* (t·cdx - pdx)² + (t·cdy - pdy)² = (r₁ + t·dr)²
|
||||
*
|
||||
* where we can actually expand the squares and solve for t:
|
||||
*
|
||||
* t²cdx² - 2t·cdx·pdx + pdx² + t²cdy² - 2t·cdy·pdy + pdy² =
|
||||
* = r₁² + 2·r₁·t·dr + t²·dr²
|
||||
*
|
||||
* (cdx² + cdy² - dr²)t² - 2(cdx·pdx + cdy·pdy + r₁·dr)t +
|
||||
* (pdx² + pdy² - r₁²) = 0
|
||||
*
|
||||
* A = cdx² + cdy² - dr²
|
||||
* B = pdx·cdx + pdy·cdy + r₁·dr
|
||||
* C = pdx² + pdy² - r₁²
|
||||
* At² - 2Bt + C = 0
|
||||
*
|
||||
* The solutions (unless the equation degenerates because of A = 0) are:
|
||||
*
|
||||
* t = (B ± ⎷(B² - A·C)) / A
|
||||
*
|
||||
* The solution we are going to prefer is the bigger one, unless the
|
||||
* radius associated to it is negative (or it falls outside the valid t
|
||||
* range).
|
||||
*
|
||||
* Additional observations (useful for optimizations):
|
||||
* A does not depend on p
|
||||
*
|
||||
* A < 0 <=> one of the two circles completely contains the other one
|
||||
* <=> for every p, the radiuses associated with the two t solutions
|
||||
* have opposite sign
|
||||
*/
|
||||
pixman_image_t *image = iter->image;
|
||||
int x = iter->x;
|
||||
int y = iter->y;
|
||||
int width = iter->width;
|
||||
uint32_t *buffer = iter->buffer;
|
||||
|
||||
gradient_t *gradient = (gradient_t *)image;
|
||||
radial_gradient_t *radial = (radial_gradient_t *)image;
|
||||
uint32_t *end = buffer + width;
|
||||
pixman_gradient_walker_t walker;
|
||||
pixman_vector_t v, unit;
|
||||
|
||||
/* reference point is the center of the pixel */
|
||||
v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2;
|
||||
v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2;
|
||||
v.vector[2] = pixman_fixed_1;
|
||||
|
||||
_pixman_gradient_walker_init (&walker, gradient, image->common.repeat);
|
||||
|
||||
if (image->common.transform)
|
||||
{
|
||||
if (!pixman_transform_point_3d (image->common.transform, &v))
|
||||
return iter->buffer;
|
||||
|
||||
unit.vector[0] = image->common.transform->matrix[0][0];
|
||||
unit.vector[1] = image->common.transform->matrix[1][0];
|
||||
unit.vector[2] = image->common.transform->matrix[2][0];
|
||||
}
|
||||
else
|
||||
{
|
||||
unit.vector[0] = pixman_fixed_1;
|
||||
unit.vector[1] = 0;
|
||||
unit.vector[2] = 0;
|
||||
}
|
||||
|
||||
if (unit.vector[2] == 0 && v.vector[2] == pixman_fixed_1)
|
||||
{
|
||||
/*
|
||||
* Given:
|
||||
*
|
||||
* t = (B ± ⎷(B² - A·C)) / A
|
||||
*
|
||||
* where
|
||||
*
|
||||
* A = cdx² + cdy² - dr²
|
||||
* B = pdx·cdx + pdy·cdy + r₁·dr
|
||||
* C = pdx² + pdy² - r₁²
|
||||
* det = B² - A·C
|
||||
*
|
||||
* Since we have an affine transformation, we know that (pdx, pdy)
|
||||
* increase linearly with each pixel,
|
||||
*
|
||||
* pdx = pdx₀ + n·ux,
|
||||
* pdy = pdy₀ + n·uy,
|
||||
*
|
||||
* we can then express B, C and det through multiple differentiation.
|
||||
*/
|
||||
pixman_fixed_32_32_t b, db, c, dc, ddc;
|
||||
|
||||
/* warning: this computation may overflow */
|
||||
v.vector[0] -= radial->c1.x;
|
||||
v.vector[1] -= radial->c1.y;
|
||||
|
||||
/*
|
||||
* B and C are computed and updated exactly.
|
||||
* If fdot was used instead of dot, in the worst case it would
|
||||
* lose 11 bits of precision in each of the multiplication and
|
||||
* summing up would zero out all the bit that were preserved,
|
||||
* thus making the result 0 instead of the correct one.
|
||||
* This would mean a worst case of unbound relative error or
|
||||
* about 2^10 absolute error
|
||||
*/
|
||||
b = dot (v.vector[0], v.vector[1], radial->c1.radius,
|
||||
radial->delta.x, radial->delta.y, radial->delta.radius);
|
||||
db = dot (unit.vector[0], unit.vector[1], 0,
|
||||
radial->delta.x, radial->delta.y, 0);
|
||||
|
||||
c = dot (v.vector[0], v.vector[1],
|
||||
-((pixman_fixed_48_16_t) radial->c1.radius),
|
||||
v.vector[0], v.vector[1], radial->c1.radius);
|
||||
dc = dot (2 * (pixman_fixed_48_16_t) v.vector[0] + unit.vector[0],
|
||||
2 * (pixman_fixed_48_16_t) v.vector[1] + unit.vector[1],
|
||||
0,
|
||||
unit.vector[0], unit.vector[1], 0);
|
||||
ddc = 2 * dot (unit.vector[0], unit.vector[1], 0,
|
||||
unit.vector[0], unit.vector[1], 0);
|
||||
|
||||
while (buffer < end)
|
||||
{
|
||||
if (!mask || *mask++)
|
||||
{
|
||||
*buffer = radial_compute_color (radial->a, b, c,
|
||||
radial->inva,
|
||||
radial->delta.radius,
|
||||
radial->mindr,
|
||||
&walker,
|
||||
image->common.repeat);
|
||||
}
|
||||
|
||||
b += db;
|
||||
c += dc;
|
||||
dc += ddc;
|
||||
++buffer;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* projective */
|
||||
/* Warning:
|
||||
* error propagation guarantees are much looser than in the affine case
|
||||
*/
|
||||
while (buffer < end)
|
||||
{
|
||||
if (!mask || *mask++)
|
||||
{
|
||||
if (v.vector[2] != 0)
|
||||
{
|
||||
double pdx, pdy, invv2, b, c;
|
||||
|
||||
invv2 = 1. * pixman_fixed_1 / v.vector[2];
|
||||
|
||||
pdx = v.vector[0] * invv2 - radial->c1.x;
|
||||
/* / pixman_fixed_1 */
|
||||
|
||||
pdy = v.vector[1] * invv2 - radial->c1.y;
|
||||
/* / pixman_fixed_1 */
|
||||
|
||||
b = fdot (pdx, pdy, radial->c1.radius,
|
||||
radial->delta.x, radial->delta.y,
|
||||
radial->delta.radius);
|
||||
/* / pixman_fixed_1 / pixman_fixed_1 */
|
||||
|
||||
c = fdot (pdx, pdy, -radial->c1.radius,
|
||||
pdx, pdy, radial->c1.radius);
|
||||
/* / pixman_fixed_1 / pixman_fixed_1 */
|
||||
|
||||
*buffer = radial_compute_color (radial->a, b, c,
|
||||
radial->inva,
|
||||
radial->delta.radius,
|
||||
radial->mindr,
|
||||
&walker,
|
||||
image->common.repeat);
|
||||
}
|
||||
else
|
||||
{
|
||||
*buffer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
++buffer;
|
||||
|
||||
v.vector[0] += unit.vector[0];
|
||||
v.vector[1] += unit.vector[1];
|
||||
v.vector[2] += unit.vector[2];
|
||||
}
|
||||
}
|
||||
|
||||
iter->y++;
|
||||
return iter->buffer;
|
||||
}
|
||||
|
||||
static uint32_t *
|
||||
radial_get_scanline_16 (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
/*
|
||||
* Implementation of radial gradients following the PDF specification.
|
||||
* See section 8.7.4.5.4 Type 3 (Radial) Shadings of the PDF Reference
|
||||
* Manual (PDF 32000-1:2008 at the time of this writing).
|
||||
*
|
||||
* In the radial gradient problem we are given two circles (c₁,r₁) and
|
||||
* (c₂,r₂) that define the gradient itself.
|
||||
*
|
||||
* Mathematically the gradient can be defined as the family of circles
|
||||
*
|
||||
* ((1-t)·c₁ + t·(c₂), (1-t)·r₁ + t·r₂)
|
||||
*
|
||||
* excluding those circles whose radius would be < 0. When a point
|
||||
* belongs to more than one circle, the one with a bigger t is the only
|
||||
* one that contributes to its color. When a point does not belong
|
||||
* to any of the circles, it is transparent black, i.e. RGBA (0, 0, 0, 0).
|
||||
* Further limitations on the range of values for t are imposed when
|
||||
* the gradient is not repeated, namely t must belong to [0,1].
|
||||
*
|
||||
* The graphical result is the same as drawing the valid (radius > 0)
|
||||
* circles with increasing t in [-inf, +inf] (or in [0,1] if the gradient
|
||||
* is not repeated) using SOURCE operator composition.
|
||||
*
|
||||
* It looks like a cone pointing towards the viewer if the ending circle
|
||||
* is smaller than the starting one, a cone pointing inside the page if
|
||||
* the starting circle is the smaller one and like a cylinder if they
|
||||
* have the same radius.
|
||||
*
|
||||
* What we actually do is, given the point whose color we are interested
|
||||
* in, compute the t values for that point, solving for t in:
|
||||
*
|
||||
* length((1-t)·c₁ + t·(c₂) - p) = (1-t)·r₁ + t·r₂
|
||||
*
|
||||
* Let's rewrite it in a simpler way, by defining some auxiliary
|
||||
* variables:
|
||||
*
|
||||
* cd = c₂ - c₁
|
||||
* pd = p - c₁
|
||||
* dr = r₂ - r₁
|
||||
* length(t·cd - pd) = r₁ + t·dr
|
||||
*
|
||||
* which actually means
|
||||
*
|
||||
* hypot(t·cdx - pdx, t·cdy - pdy) = r₁ + t·dr
|
||||
*
|
||||
* or
|
||||
*
|
||||
* ⎷((t·cdx - pdx)² + (t·cdy - pdy)²) = r₁ + t·dr.
|
||||
*
|
||||
* If we impose (as stated earlier) that r₁ + t·dr >= 0, it becomes:
|
||||
*
|
||||
* (t·cdx - pdx)² + (t·cdy - pdy)² = (r₁ + t·dr)²
|
||||
*
|
||||
* where we can actually expand the squares and solve for t:
|
||||
*
|
||||
* t²cdx² - 2t·cdx·pdx + pdx² + t²cdy² - 2t·cdy·pdy + pdy² =
|
||||
* = r₁² + 2·r₁·t·dr + t²·dr²
|
||||
*
|
||||
* (cdx² + cdy² - dr²)t² - 2(cdx·pdx + cdy·pdy + r₁·dr)t +
|
||||
* (pdx² + pdy² - r₁²) = 0
|
||||
*
|
||||
* A = cdx² + cdy² - dr²
|
||||
* B = pdx·cdx + pdy·cdy + r₁·dr
|
||||
* C = pdx² + pdy² - r₁²
|
||||
* At² - 2Bt + C = 0
|
||||
*
|
||||
* The solutions (unless the equation degenerates because of A = 0) are:
|
||||
*
|
||||
* t = (B ± ⎷(B² - A·C)) / A
|
||||
*
|
||||
* The solution we are going to prefer is the bigger one, unless the
|
||||
* radius associated to it is negative (or it falls outside the valid t
|
||||
* range).
|
||||
*
|
||||
* Additional observations (useful for optimizations):
|
||||
* A does not depend on p
|
||||
*
|
||||
* A < 0 <=> one of the two circles completely contains the other one
|
||||
* <=> for every p, the radiuses associated with the two t solutions
|
||||
* have opposite sign
|
||||
*/
|
||||
pixman_image_t *image = iter->image;
|
||||
int x = iter->x;
|
||||
int y = iter->y;
|
||||
int width = iter->width;
|
||||
uint16_t *buffer = iter->buffer;
|
||||
pixman_bool_t toggle = ((x ^ y) & 1);
|
||||
|
||||
gradient_t *gradient = (gradient_t *)image;
|
||||
radial_gradient_t *radial = (radial_gradient_t *)image;
|
||||
uint16_t *end = buffer + width;
|
||||
pixman_gradient_walker_t walker;
|
||||
pixman_vector_t v, unit;
|
||||
|
||||
/* reference point is the center of the pixel */
|
||||
v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2;
|
||||
v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2;
|
||||
v.vector[2] = pixman_fixed_1;
|
||||
|
||||
_pixman_gradient_walker_init (&walker, gradient, image->common.repeat);
|
||||
|
||||
if (image->common.transform)
|
||||
{
|
||||
if (!pixman_transform_point_3d (image->common.transform, &v))
|
||||
return iter->buffer;
|
||||
|
||||
unit.vector[0] = image->common.transform->matrix[0][0];
|
||||
unit.vector[1] = image->common.transform->matrix[1][0];
|
||||
unit.vector[2] = image->common.transform->matrix[2][0];
|
||||
}
|
||||
else
|
||||
{
|
||||
unit.vector[0] = pixman_fixed_1;
|
||||
unit.vector[1] = 0;
|
||||
unit.vector[2] = 0;
|
||||
}
|
||||
|
||||
if (unit.vector[2] == 0 && v.vector[2] == pixman_fixed_1)
|
||||
{
|
||||
/*
|
||||
* Given:
|
||||
*
|
||||
* t = (B ± ⎷(B² - A·C)) / A
|
||||
*
|
||||
* where
|
||||
*
|
||||
* A = cdx² + cdy² - dr²
|
||||
* B = pdx·cdx + pdy·cdy + r₁·dr
|
||||
* C = pdx² + pdy² - r₁²
|
||||
* det = B² - A·C
|
||||
*
|
||||
* Since we have an affine transformation, we know that (pdx, pdy)
|
||||
* increase linearly with each pixel,
|
||||
*
|
||||
* pdx = pdx₀ + n·ux,
|
||||
* pdy = pdy₀ + n·uy,
|
||||
*
|
||||
* we can then express B, C and det through multiple differentiation.
|
||||
*/
|
||||
pixman_fixed_32_32_t b, db, c, dc, ddc;
|
||||
|
||||
/* warning: this computation may overflow */
|
||||
v.vector[0] -= radial->c1.x;
|
||||
v.vector[1] -= radial->c1.y;
|
||||
|
||||
/*
|
||||
* B and C are computed and updated exactly.
|
||||
* If fdot was used instead of dot, in the worst case it would
|
||||
* lose 11 bits of precision in each of the multiplication and
|
||||
* summing up would zero out all the bit that were preserved,
|
||||
* thus making the result 0 instead of the correct one.
|
||||
* This would mean a worst case of unbound relative error or
|
||||
* about 2^10 absolute error
|
||||
*/
|
||||
b = dot (v.vector[0], v.vector[1], radial->c1.radius,
|
||||
radial->delta.x, radial->delta.y, radial->delta.radius);
|
||||
db = dot (unit.vector[0], unit.vector[1], 0,
|
||||
radial->delta.x, radial->delta.y, 0);
|
||||
|
||||
c = dot (v.vector[0], v.vector[1],
|
||||
-((pixman_fixed_48_16_t) radial->c1.radius),
|
||||
v.vector[0], v.vector[1], radial->c1.radius);
|
||||
dc = dot (2 * (pixman_fixed_48_16_t) v.vector[0] + unit.vector[0],
|
||||
2 * (pixman_fixed_48_16_t) v.vector[1] + unit.vector[1],
|
||||
0,
|
||||
unit.vector[0], unit.vector[1], 0);
|
||||
ddc = 2 * dot (unit.vector[0], unit.vector[1], 0,
|
||||
unit.vector[0], unit.vector[1], 0);
|
||||
|
||||
while (buffer < end)
|
||||
{
|
||||
if (!mask || *mask++)
|
||||
{
|
||||
*buffer = dither_8888_to_0565(
|
||||
radial_compute_color (radial->a, b, c,
|
||||
radial->inva,
|
||||
radial->delta.radius,
|
||||
radial->mindr,
|
||||
&walker,
|
||||
image->common.repeat),
|
||||
toggle);
|
||||
}
|
||||
|
||||
toggle ^= 1;
|
||||
b += db;
|
||||
c += dc;
|
||||
dc += ddc;
|
||||
++buffer;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* projective */
|
||||
/* Warning:
|
||||
* error propagation guarantees are much looser than in the affine case
|
||||
*/
|
||||
while (buffer < end)
|
||||
{
|
||||
if (!mask || *mask++)
|
||||
{
|
||||
if (v.vector[2] != 0)
|
||||
{
|
||||
double pdx, pdy, invv2, b, c;
|
||||
|
||||
invv2 = 1. * pixman_fixed_1 / v.vector[2];
|
||||
|
||||
pdx = v.vector[0] * invv2 - radial->c1.x;
|
||||
/* / pixman_fixed_1 */
|
||||
|
||||
pdy = v.vector[1] * invv2 - radial->c1.y;
|
||||
/* / pixman_fixed_1 */
|
||||
|
||||
b = fdot (pdx, pdy, radial->c1.radius,
|
||||
radial->delta.x, radial->delta.y,
|
||||
radial->delta.radius);
|
||||
/* / pixman_fixed_1 / pixman_fixed_1 */
|
||||
|
||||
c = fdot (pdx, pdy, -radial->c1.radius,
|
||||
pdx, pdy, radial->c1.radius);
|
||||
/* / pixman_fixed_1 / pixman_fixed_1 */
|
||||
|
||||
*buffer = dither_8888_to_0565 (
|
||||
radial_compute_color (radial->a, b, c,
|
||||
radial->inva,
|
||||
radial->delta.radius,
|
||||
radial->mindr,
|
||||
&walker,
|
||||
image->common.repeat),
|
||||
toggle);
|
||||
}
|
||||
else
|
||||
{
|
||||
*buffer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
++buffer;
|
||||
toggle ^= 1;
|
||||
|
||||
v.vector[0] += unit.vector[0];
|
||||
v.vector[1] += unit.vector[1];
|
||||
v.vector[2] += unit.vector[2];
|
||||
}
|
||||
}
|
||||
|
||||
iter->y++;
|
||||
return iter->buffer;
|
||||
}
|
||||
static uint32_t *
|
||||
radial_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
uint32_t *buffer = radial_get_scanline_narrow (iter, NULL);
|
||||
|
||||
pixman_expand_to_float (
|
||||
(argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void
|
||||
_pixman_radial_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter)
|
||||
{
|
||||
if (iter->iter_flags & ITER_16)
|
||||
iter->get_scanline = radial_get_scanline_16;
|
||||
else if (iter->iter_flags & ITER_NARROW)
|
||||
iter->get_scanline = radial_get_scanline_narrow;
|
||||
else
|
||||
iter->get_scanline = radial_get_scanline_wide;
|
||||
}
|
||||
|
||||
|
||||
PIXMAN_EXPORT pixman_image_t *
|
||||
pixman_image_create_radial_gradient (const pixman_point_fixed_t * inner,
|
||||
const pixman_point_fixed_t * outer,
|
||||
pixman_fixed_t inner_radius,
|
||||
pixman_fixed_t outer_radius,
|
||||
const pixman_gradient_stop_t *stops,
|
||||
int n_stops)
|
||||
{
|
||||
pixman_image_t *image;
|
||||
radial_gradient_t *radial;
|
||||
|
||||
image = _pixman_image_allocate ();
|
||||
|
||||
if (!image)
|
||||
return NULL;
|
||||
|
||||
radial = &image->radial;
|
||||
|
||||
if (!_pixman_init_gradient (&radial->common, stops, n_stops))
|
||||
{
|
||||
free (image);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
image->type = RADIAL;
|
||||
|
||||
radial->c1.x = inner->x;
|
||||
radial->c1.y = inner->y;
|
||||
radial->c1.radius = inner_radius;
|
||||
radial->c2.x = outer->x;
|
||||
radial->c2.y = outer->y;
|
||||
radial->c2.radius = outer_radius;
|
||||
|
||||
/* warning: this computations may overflow */
|
||||
radial->delta.x = radial->c2.x - radial->c1.x;
|
||||
radial->delta.y = radial->c2.y - radial->c1.y;
|
||||
radial->delta.radius = radial->c2.radius - radial->c1.radius;
|
||||
|
||||
/* computed exactly, then cast to double -> every bit of the double
|
||||
representation is correct (53 bits) */
|
||||
radial->a = dot (radial->delta.x, radial->delta.y, -radial->delta.radius,
|
||||
radial->delta.x, radial->delta.y, radial->delta.radius);
|
||||
if (radial->a != 0)
|
||||
radial->inva = 1. * pixman_fixed_1 / radial->a;
|
||||
|
||||
radial->mindr = -1. * pixman_fixed_1 * radial->c1.radius;
|
||||
|
||||
return image;
|
||||
}
|
||||
2808
gfx/cairo/libpixman/src/pixman-region.c
Normal file
2808
gfx/cairo/libpixman/src/pixman-region.c
Normal file
File diff suppressed because it is too large
Load diff
67
gfx/cairo/libpixman/src/pixman-region16.c
Normal file
67
gfx/cairo/libpixman/src/pixman-region16.c
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright © 2008 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software
|
||||
* and its documentation for any purpose is hereby granted without
|
||||
* fee, provided that the above copyright notice appear in all copies
|
||||
* and that both that copyright notice and this permission notice
|
||||
* appear in supporting documentation, and that the name of
|
||||
* Red Hat, Inc. not be used in advertising or publicity pertaining to
|
||||
* distribution of the software without specific, written prior
|
||||
* permission. Red Hat, Inc. makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
|
||||
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Author: Soren Sandmann <sandmann@redhat.com>
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#undef PIXMAN_DISABLE_DEPRECATED
|
||||
|
||||
#include "pixman-private.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef pixman_box16_t box_type_t;
|
||||
typedef pixman_region16_data_t region_data_type_t;
|
||||
typedef pixman_region16_t region_type_t;
|
||||
typedef int32_t overflow_int_t;
|
||||
|
||||
typedef struct {
|
||||
int x, y;
|
||||
} point_type_t;
|
||||
|
||||
#define PREFIX(x) pixman_region##x
|
||||
|
||||
#define PIXMAN_REGION_MAX INT16_MAX
|
||||
#define PIXMAN_REGION_MIN INT16_MIN
|
||||
|
||||
#include "pixman-region.c"
|
||||
|
||||
/* This function exists only to make it possible to preserve the X ABI -
|
||||
* it should go away at first opportunity.
|
||||
*
|
||||
* The problem is that the X ABI exports the three structs and has used
|
||||
* them through macros. So the X server calls this function with
|
||||
* the addresses of those structs which makes the existing code continue to
|
||||
* work.
|
||||
*/
|
||||
PIXMAN_EXPORT void
|
||||
pixman_region_set_static_pointers (pixman_box16_t *empty_box,
|
||||
pixman_region16_data_t *empty_data,
|
||||
pixman_region16_data_t *broken_data)
|
||||
{
|
||||
pixman_region_empty_box = empty_box;
|
||||
pixman_region_empty_data = empty_data;
|
||||
pixman_broken_data = broken_data;
|
||||
}
|
||||
47
gfx/cairo/libpixman/src/pixman-region32.c
Normal file
47
gfx/cairo/libpixman/src/pixman-region32.c
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright © 2008 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software
|
||||
* and its documentation for any purpose is hereby granted without
|
||||
* fee, provided that the above copyright notice appear in all copies
|
||||
* and that both that copyright notice and this permission notice
|
||||
* appear in supporting documentation, and that the name of
|
||||
* Red Hat, Inc. not be used in advertising or publicity pertaining to
|
||||
* distribution of the software without specific, written prior
|
||||
* permission. Red Hat, Inc. makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
|
||||
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Author: Soren Sandmann <sandmann@redhat.com>
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "pixman-private.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef pixman_box32_t box_type_t;
|
||||
typedef pixman_region32_data_t region_data_type_t;
|
||||
typedef pixman_region32_t region_type_t;
|
||||
typedef int64_t overflow_int_t;
|
||||
|
||||
typedef struct {
|
||||
int x, y;
|
||||
} point_type_t;
|
||||
|
||||
#define PREFIX(x) pixman_region32##x
|
||||
|
||||
#define PIXMAN_REGION_MAX INT32_MAX
|
||||
#define PIXMAN_REGION_MIN INT32_MIN
|
||||
|
||||
#include "pixman-region.c"
|
||||
67
gfx/cairo/libpixman/src/pixman-solid-fill.c
Normal file
67
gfx/cairo/libpixman/src/pixman-solid-fill.c
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright © 2000 SuSE, Inc.
|
||||
* Copyright © 2007, 2009 Red Hat, Inc.
|
||||
* Copyright © 2009 Soren Sandmann
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of SuSE not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. SuSE makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
|
||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include "pixman-private.h"
|
||||
|
||||
static uint32_t
|
||||
color_to_uint32 (const pixman_color_t *color)
|
||||
{
|
||||
return
|
||||
(color->alpha >> 8 << 24) |
|
||||
(color->red >> 8 << 16) |
|
||||
(color->green & 0xff00) |
|
||||
(color->blue >> 8);
|
||||
}
|
||||
|
||||
static argb_t
|
||||
color_to_float (const pixman_color_t *color)
|
||||
{
|
||||
argb_t result;
|
||||
|
||||
result.a = pixman_unorm_to_float (color->alpha, 16);
|
||||
result.r = pixman_unorm_to_float (color->red, 16);
|
||||
result.g = pixman_unorm_to_float (color->green, 16);
|
||||
result.b = pixman_unorm_to_float (color->blue, 16);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT pixman_image_t *
|
||||
pixman_image_create_solid_fill (const pixman_color_t *color)
|
||||
{
|
||||
pixman_image_t *img = _pixman_image_allocate ();
|
||||
|
||||
if (!img)
|
||||
return NULL;
|
||||
|
||||
img->type = SOLID;
|
||||
img->solid.color = *color;
|
||||
img->solid.color_32 = color_to_uint32 (color);
|
||||
img->solid.color_float = color_to_float (color);
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
6560
gfx/cairo/libpixman/src/pixman-sse2.c
Normal file
6560
gfx/cairo/libpixman/src/pixman-sse2.c
Normal file
File diff suppressed because it is too large
Load diff
66
gfx/cairo/libpixman/src/pixman-timer.c
Normal file
66
gfx/cairo/libpixman/src/pixman-timer.c
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright © 2007 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Red Hat not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. Red Hat makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
|
||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "pixman-private.h"
|
||||
|
||||
#ifdef PIXMAN_TIMERS
|
||||
|
||||
static pixman_timer_t *timers;
|
||||
|
||||
static void
|
||||
dump_timers (void)
|
||||
{
|
||||
pixman_timer_t *timer;
|
||||
|
||||
for (timer = timers; timer != NULL; timer = timer->next)
|
||||
{
|
||||
printf ("%s: total: %llu n: %llu avg: %f\n",
|
||||
timer->name,
|
||||
timer->total,
|
||||
timer->n_times,
|
||||
timer->total / (double)timer->n_times);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pixman_timer_register (pixman_timer_t *timer)
|
||||
{
|
||||
static int initialized;
|
||||
|
||||
int atexit (void (*function)(void));
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
atexit (dump_timers);
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
timer->next = timers;
|
||||
timers = timer;
|
||||
}
|
||||
|
||||
#endif
|
||||
711
gfx/cairo/libpixman/src/pixman-trap.c
Normal file
711
gfx/cairo/libpixman/src/pixman-trap.c
Normal file
|
|
@ -0,0 +1,711 @@
|
|||
/*
|
||||
* Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
|
||||
* Copyright © 2004 Keith Packard
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "pixman-private.h"
|
||||
|
||||
/*
|
||||
* Compute the smallest value greater than or equal to y which is on a
|
||||
* grid row.
|
||||
*/
|
||||
|
||||
PIXMAN_EXPORT pixman_fixed_t
|
||||
pixman_sample_ceil_y (pixman_fixed_t y, int n)
|
||||
{
|
||||
pixman_fixed_t f = pixman_fixed_frac (y);
|
||||
pixman_fixed_t i = pixman_fixed_floor (y);
|
||||
|
||||
f = DIV (f - Y_FRAC_FIRST (n) + (STEP_Y_SMALL (n) - pixman_fixed_e), STEP_Y_SMALL (n)) * STEP_Y_SMALL (n) +
|
||||
Y_FRAC_FIRST (n);
|
||||
|
||||
if (f > Y_FRAC_LAST (n))
|
||||
{
|
||||
if (pixman_fixed_to_int (i) == 0x7fff)
|
||||
{
|
||||
f = 0xffff; /* saturate */
|
||||
}
|
||||
else
|
||||
{
|
||||
f = Y_FRAC_FIRST (n);
|
||||
i += pixman_fixed_1;
|
||||
}
|
||||
}
|
||||
return (i | f);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the largest value strictly less than y which is on a
|
||||
* grid row.
|
||||
*/
|
||||
PIXMAN_EXPORT pixman_fixed_t
|
||||
pixman_sample_floor_y (pixman_fixed_t y,
|
||||
int n)
|
||||
{
|
||||
pixman_fixed_t f = pixman_fixed_frac (y);
|
||||
pixman_fixed_t i = pixman_fixed_floor (y);
|
||||
|
||||
f = DIV (f - pixman_fixed_e - Y_FRAC_FIRST (n), STEP_Y_SMALL (n)) * STEP_Y_SMALL (n) +
|
||||
Y_FRAC_FIRST (n);
|
||||
|
||||
if (f < Y_FRAC_FIRST (n))
|
||||
{
|
||||
if (pixman_fixed_to_int (i) == 0x8000)
|
||||
{
|
||||
f = 0; /* saturate */
|
||||
}
|
||||
else
|
||||
{
|
||||
f = Y_FRAC_LAST (n);
|
||||
i -= pixman_fixed_1;
|
||||
}
|
||||
}
|
||||
return (i | f);
|
||||
}
|
||||
|
||||
/*
|
||||
* Step an edge by any amount (including negative values)
|
||||
*/
|
||||
PIXMAN_EXPORT void
|
||||
pixman_edge_step (pixman_edge_t *e,
|
||||
int n)
|
||||
{
|
||||
pixman_fixed_48_16_t ne;
|
||||
|
||||
e->x += n * e->stepx;
|
||||
|
||||
ne = e->e + n * (pixman_fixed_48_16_t) e->dx;
|
||||
|
||||
if (n >= 0)
|
||||
{
|
||||
if (ne > 0)
|
||||
{
|
||||
int nx = (ne + e->dy - 1) / e->dy;
|
||||
e->e = ne - nx * (pixman_fixed_48_16_t) e->dy;
|
||||
e->x += nx * e->signdx;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ne <= -e->dy)
|
||||
{
|
||||
int nx = (-ne) / e->dy;
|
||||
e->e = ne + nx * (pixman_fixed_48_16_t) e->dy;
|
||||
e->x -= nx * e->signdx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A private routine to initialize the multi-step
|
||||
* elements of an edge structure
|
||||
*/
|
||||
static void
|
||||
_pixman_edge_multi_init (pixman_edge_t * e,
|
||||
int n,
|
||||
pixman_fixed_t *stepx_p,
|
||||
pixman_fixed_t *dx_p)
|
||||
{
|
||||
pixman_fixed_t stepx;
|
||||
pixman_fixed_48_16_t ne;
|
||||
|
||||
ne = n * (pixman_fixed_48_16_t) e->dx;
|
||||
stepx = n * e->stepx;
|
||||
|
||||
if (ne > 0)
|
||||
{
|
||||
int nx = ne / e->dy;
|
||||
ne -= nx * (pixman_fixed_48_16_t)e->dy;
|
||||
stepx += nx * e->signdx;
|
||||
}
|
||||
|
||||
*dx_p = ne;
|
||||
*stepx_p = stepx;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize one edge structure given the line endpoints and a
|
||||
* starting y value
|
||||
*/
|
||||
PIXMAN_EXPORT void
|
||||
pixman_edge_init (pixman_edge_t *e,
|
||||
int n,
|
||||
pixman_fixed_t y_start,
|
||||
pixman_fixed_t x_top,
|
||||
pixman_fixed_t y_top,
|
||||
pixman_fixed_t x_bot,
|
||||
pixman_fixed_t y_bot)
|
||||
{
|
||||
pixman_fixed_t dx, dy;
|
||||
|
||||
e->x = x_top;
|
||||
e->e = 0;
|
||||
dx = x_bot - x_top;
|
||||
dy = y_bot - y_top;
|
||||
e->dy = dy;
|
||||
e->dx = 0;
|
||||
|
||||
if (dy)
|
||||
{
|
||||
if (dx >= 0)
|
||||
{
|
||||
e->signdx = 1;
|
||||
e->stepx = dx / dy;
|
||||
e->dx = dx % dy;
|
||||
e->e = -dy;
|
||||
}
|
||||
else
|
||||
{
|
||||
e->signdx = -1;
|
||||
e->stepx = -(-dx / dy);
|
||||
e->dx = -dx % dy;
|
||||
e->e = 0;
|
||||
}
|
||||
|
||||
_pixman_edge_multi_init (e, STEP_Y_SMALL (n),
|
||||
&e->stepx_small, &e->dx_small);
|
||||
|
||||
_pixman_edge_multi_init (e, STEP_Y_BIG (n),
|
||||
&e->stepx_big, &e->dx_big);
|
||||
}
|
||||
pixman_edge_step (e, y_start - y_top);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize one edge structure given a line, starting y value
|
||||
* and a pixel offset for the line
|
||||
*/
|
||||
PIXMAN_EXPORT void
|
||||
pixman_line_fixed_edge_init (pixman_edge_t * e,
|
||||
int n,
|
||||
pixman_fixed_t y,
|
||||
const pixman_line_fixed_t *line,
|
||||
int x_off,
|
||||
int y_off)
|
||||
{
|
||||
pixman_fixed_t x_off_fixed = pixman_int_to_fixed (x_off);
|
||||
pixman_fixed_t y_off_fixed = pixman_int_to_fixed (y_off);
|
||||
const pixman_point_fixed_t *top, *bot;
|
||||
|
||||
if (line->p1.y <= line->p2.y)
|
||||
{
|
||||
top = &line->p1;
|
||||
bot = &line->p2;
|
||||
}
|
||||
else
|
||||
{
|
||||
top = &line->p2;
|
||||
bot = &line->p1;
|
||||
}
|
||||
|
||||
pixman_edge_init (e, n, y,
|
||||
top->x + x_off_fixed,
|
||||
top->y + y_off_fixed,
|
||||
bot->x + x_off_fixed,
|
||||
bot->y + y_off_fixed);
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_add_traps (pixman_image_t * image,
|
||||
int16_t x_off,
|
||||
int16_t y_off,
|
||||
int ntrap,
|
||||
const pixman_trap_t *traps)
|
||||
{
|
||||
int bpp;
|
||||
int height;
|
||||
|
||||
pixman_fixed_t x_off_fixed;
|
||||
pixman_fixed_t y_off_fixed;
|
||||
pixman_edge_t l, r;
|
||||
pixman_fixed_t t, b;
|
||||
|
||||
_pixman_image_validate (image);
|
||||
|
||||
height = image->bits.height;
|
||||
bpp = PIXMAN_FORMAT_BPP (image->bits.format);
|
||||
|
||||
x_off_fixed = pixman_int_to_fixed (x_off);
|
||||
y_off_fixed = pixman_int_to_fixed (y_off);
|
||||
|
||||
while (ntrap--)
|
||||
{
|
||||
t = traps->top.y + y_off_fixed;
|
||||
if (t < 0)
|
||||
t = 0;
|
||||
t = pixman_sample_ceil_y (t, bpp);
|
||||
|
||||
b = traps->bot.y + y_off_fixed;
|
||||
if (pixman_fixed_to_int (b) >= height)
|
||||
b = pixman_int_to_fixed (height) - 1;
|
||||
b = pixman_sample_floor_y (b, bpp);
|
||||
|
||||
if (b >= t)
|
||||
{
|
||||
/* initialize edge walkers */
|
||||
pixman_edge_init (&l, bpp, t,
|
||||
traps->top.l + x_off_fixed,
|
||||
traps->top.y + y_off_fixed,
|
||||
traps->bot.l + x_off_fixed,
|
||||
traps->bot.y + y_off_fixed);
|
||||
|
||||
pixman_edge_init (&r, bpp, t,
|
||||
traps->top.r + x_off_fixed,
|
||||
traps->top.y + y_off_fixed,
|
||||
traps->bot.r + x_off_fixed,
|
||||
traps->bot.y + y_off_fixed);
|
||||
|
||||
pixman_rasterize_edges (image, &l, &r, t, b);
|
||||
}
|
||||
|
||||
traps++;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
dump_image (pixman_image_t *image,
|
||||
const char * title)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (!image->type == BITS)
|
||||
printf ("%s is not a regular image\n", title);
|
||||
|
||||
if (!image->bits.format == PIXMAN_a8)
|
||||
printf ("%s is not an alpha mask\n", title);
|
||||
|
||||
printf ("\n\n\n%s: \n", title);
|
||||
|
||||
for (i = 0; i < image->bits.height; ++i)
|
||||
{
|
||||
uint8_t *line =
|
||||
(uint8_t *)&(image->bits.bits[i * image->bits.rowstride]);
|
||||
|
||||
for (j = 0; j < image->bits.width; ++j)
|
||||
printf ("%c", line[j] ? '#' : ' ');
|
||||
|
||||
printf ("\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_add_trapezoids (pixman_image_t * image,
|
||||
int16_t x_off,
|
||||
int y_off,
|
||||
int ntraps,
|
||||
const pixman_trapezoid_t *traps)
|
||||
{
|
||||
int i;
|
||||
|
||||
#if 0
|
||||
dump_image (image, "before");
|
||||
#endif
|
||||
|
||||
for (i = 0; i < ntraps; ++i)
|
||||
{
|
||||
const pixman_trapezoid_t *trap = &(traps[i]);
|
||||
|
||||
if (!pixman_trapezoid_valid (trap))
|
||||
continue;
|
||||
|
||||
pixman_rasterize_trapezoid (image, trap, x_off, y_off);
|
||||
}
|
||||
|
||||
#if 0
|
||||
dump_image (image, "after");
|
||||
#endif
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_rasterize_trapezoid (pixman_image_t * image,
|
||||
const pixman_trapezoid_t *trap,
|
||||
int x_off,
|
||||
int y_off)
|
||||
{
|
||||
int bpp;
|
||||
int height;
|
||||
|
||||
pixman_fixed_t y_off_fixed;
|
||||
pixman_edge_t l, r;
|
||||
pixman_fixed_t t, b;
|
||||
|
||||
return_if_fail (image->type == BITS);
|
||||
|
||||
_pixman_image_validate (image);
|
||||
|
||||
if (!pixman_trapezoid_valid (trap))
|
||||
return;
|
||||
|
||||
height = image->bits.height;
|
||||
bpp = PIXMAN_FORMAT_BPP (image->bits.format);
|
||||
|
||||
y_off_fixed = pixman_int_to_fixed (y_off);
|
||||
|
||||
t = trap->top + y_off_fixed;
|
||||
if (t < 0)
|
||||
t = 0;
|
||||
t = pixman_sample_ceil_y (t, bpp);
|
||||
|
||||
b = trap->bottom + y_off_fixed;
|
||||
if (pixman_fixed_to_int (b) >= height)
|
||||
b = pixman_int_to_fixed (height) - 1;
|
||||
b = pixman_sample_floor_y (b, bpp);
|
||||
|
||||
if (b >= t)
|
||||
{
|
||||
/* initialize edge walkers */
|
||||
pixman_line_fixed_edge_init (&l, bpp, t, &trap->left, x_off, y_off);
|
||||
pixman_line_fixed_edge_init (&r, bpp, t, &trap->right, x_off, y_off);
|
||||
|
||||
pixman_rasterize_edges (image, &l, &r, t, b);
|
||||
}
|
||||
}
|
||||
|
||||
static const pixman_bool_t zero_src_has_no_effect[PIXMAN_N_OPERATORS] =
|
||||
{
|
||||
FALSE, /* Clear 0 0 */
|
||||
FALSE, /* Src 1 0 */
|
||||
TRUE, /* Dst 0 1 */
|
||||
TRUE, /* Over 1 1-Aa */
|
||||
TRUE, /* OverReverse 1-Ab 1 */
|
||||
FALSE, /* In Ab 0 */
|
||||
FALSE, /* InReverse 0 Aa */
|
||||
FALSE, /* Out 1-Ab 0 */
|
||||
TRUE, /* OutReverse 0 1-Aa */
|
||||
TRUE, /* Atop Ab 1-Aa */
|
||||
FALSE, /* AtopReverse 1-Ab Aa */
|
||||
TRUE, /* Xor 1-Ab 1-Aa */
|
||||
TRUE, /* Add 1 1 */
|
||||
};
|
||||
|
||||
static pixman_bool_t
|
||||
get_trap_extents (pixman_op_t op, pixman_image_t *dest,
|
||||
const pixman_trapezoid_t *traps, int n_traps,
|
||||
pixman_box32_t *box)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* When the operator is such that a zero source has an
|
||||
* effect on the underlying image, we have to
|
||||
* composite across the entire destination
|
||||
*/
|
||||
if (!zero_src_has_no_effect [op])
|
||||
{
|
||||
box->x1 = 0;
|
||||
box->y1 = 0;
|
||||
box->x2 = dest->bits.width;
|
||||
box->y2 = dest->bits.height;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
box->x1 = INT32_MAX;
|
||||
box->y1 = INT32_MAX;
|
||||
box->x2 = INT32_MIN;
|
||||
box->y2 = INT32_MIN;
|
||||
|
||||
for (i = 0; i < n_traps; ++i)
|
||||
{
|
||||
const pixman_trapezoid_t *trap = &(traps[i]);
|
||||
int y1, y2;
|
||||
|
||||
if (!pixman_trapezoid_valid (trap))
|
||||
continue;
|
||||
|
||||
y1 = pixman_fixed_to_int (trap->top);
|
||||
if (y1 < box->y1)
|
||||
box->y1 = y1;
|
||||
|
||||
y2 = pixman_fixed_to_int (pixman_fixed_ceil (trap->bottom));
|
||||
if (y2 > box->y2)
|
||||
box->y2 = y2;
|
||||
|
||||
#define EXTEND_MIN(x) \
|
||||
if (pixman_fixed_to_int ((x)) < box->x1) \
|
||||
box->x1 = pixman_fixed_to_int ((x));
|
||||
#define EXTEND_MAX(x) \
|
||||
if (pixman_fixed_to_int (pixman_fixed_ceil ((x))) > box->x2) \
|
||||
box->x2 = pixman_fixed_to_int (pixman_fixed_ceil ((x)));
|
||||
|
||||
#define EXTEND(x) \
|
||||
EXTEND_MIN(x); \
|
||||
EXTEND_MAX(x);
|
||||
|
||||
EXTEND(trap->left.p1.x);
|
||||
EXTEND(trap->left.p2.x);
|
||||
EXTEND(trap->right.p1.x);
|
||||
EXTEND(trap->right.p2.x);
|
||||
}
|
||||
|
||||
if (box->x1 >= box->x2 || box->y1 >= box->y2)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* pixman_composite_trapezoids()
|
||||
*
|
||||
* All the trapezoids are conceptually rendered to an infinitely big image.
|
||||
* The (0, 0) coordinates of this image are then aligned with the (x, y)
|
||||
* coordinates of the source image, and then both images are aligned with
|
||||
* the (x, y) coordinates of the destination. Then these three images are
|
||||
* composited across the entire destination.
|
||||
*/
|
||||
PIXMAN_EXPORT void
|
||||
pixman_composite_trapezoids (pixman_op_t op,
|
||||
pixman_image_t * src,
|
||||
pixman_image_t * dst,
|
||||
pixman_format_code_t mask_format,
|
||||
int x_src,
|
||||
int y_src,
|
||||
int x_dst,
|
||||
int y_dst,
|
||||
int n_traps,
|
||||
const pixman_trapezoid_t * traps)
|
||||
{
|
||||
int i;
|
||||
|
||||
return_if_fail (PIXMAN_FORMAT_TYPE (mask_format) == PIXMAN_TYPE_A);
|
||||
|
||||
if (n_traps <= 0)
|
||||
return;
|
||||
|
||||
_pixman_image_validate (src);
|
||||
_pixman_image_validate (dst);
|
||||
|
||||
if (op == PIXMAN_OP_ADD &&
|
||||
(src->common.flags & FAST_PATH_IS_OPAQUE) &&
|
||||
(mask_format == dst->common.extended_format_code) &&
|
||||
!(dst->common.have_clip_region))
|
||||
{
|
||||
for (i = 0; i < n_traps; ++i)
|
||||
{
|
||||
const pixman_trapezoid_t *trap = &(traps[i]);
|
||||
|
||||
if (!pixman_trapezoid_valid (trap))
|
||||
continue;
|
||||
|
||||
pixman_rasterize_trapezoid (dst, trap, x_dst, y_dst);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pixman_image_t *tmp;
|
||||
pixman_box32_t box;
|
||||
int i;
|
||||
|
||||
if (!get_trap_extents (op, dst, traps, n_traps, &box))
|
||||
return;
|
||||
|
||||
if (!(tmp = pixman_image_create_bits (
|
||||
mask_format, box.x2 - box.x1, box.y2 - box.y1, NULL, -1)))
|
||||
return;
|
||||
|
||||
for (i = 0; i < n_traps; ++i)
|
||||
{
|
||||
const pixman_trapezoid_t *trap = &(traps[i]);
|
||||
|
||||
if (!pixman_trapezoid_valid (trap))
|
||||
continue;
|
||||
|
||||
pixman_rasterize_trapezoid (tmp, trap, - box.x1, - box.y1);
|
||||
}
|
||||
|
||||
pixman_image_composite (op, src, tmp, dst,
|
||||
x_src + box.x1, y_src + box.y1,
|
||||
0, 0,
|
||||
x_dst + box.x1, y_dst + box.y1,
|
||||
box.x2 - box.x1, box.y2 - box.y1);
|
||||
|
||||
pixman_image_unref (tmp);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
greater_y (const pixman_point_fixed_t *a, const pixman_point_fixed_t *b)
|
||||
{
|
||||
if (a->y == b->y)
|
||||
return a->x > b->x;
|
||||
return a->y > b->y;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that the definition of this function is a bit odd because
|
||||
* of the X coordinate space (y increasing downwards).
|
||||
*/
|
||||
static int
|
||||
clockwise (const pixman_point_fixed_t *ref,
|
||||
const pixman_point_fixed_t *a,
|
||||
const pixman_point_fixed_t *b)
|
||||
{
|
||||
pixman_point_fixed_t ad, bd;
|
||||
|
||||
ad.x = a->x - ref->x;
|
||||
ad.y = a->y - ref->y;
|
||||
bd.x = b->x - ref->x;
|
||||
bd.y = b->y - ref->y;
|
||||
|
||||
return ((pixman_fixed_32_32_t) bd.y * ad.x -
|
||||
(pixman_fixed_32_32_t) ad.y * bd.x) < 0;
|
||||
}
|
||||
|
||||
static void
|
||||
triangle_to_trapezoids (const pixman_triangle_t *tri, pixman_trapezoid_t *traps)
|
||||
{
|
||||
const pixman_point_fixed_t *top, *left, *right, *tmp;
|
||||
|
||||
top = &tri->p1;
|
||||
left = &tri->p2;
|
||||
right = &tri->p3;
|
||||
|
||||
if (greater_y (top, left))
|
||||
{
|
||||
tmp = left;
|
||||
left = top;
|
||||
top = tmp;
|
||||
}
|
||||
|
||||
if (greater_y (top, right))
|
||||
{
|
||||
tmp = right;
|
||||
right = top;
|
||||
top = tmp;
|
||||
}
|
||||
|
||||
if (clockwise (top, right, left))
|
||||
{
|
||||
tmp = right;
|
||||
right = left;
|
||||
left = tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Two cases:
|
||||
*
|
||||
* + +
|
||||
* / \ / \
|
||||
* / \ / \
|
||||
* / + + \
|
||||
* / -- -- \
|
||||
* / -- -- \
|
||||
* / --- --- \
|
||||
* +-- --+
|
||||
*/
|
||||
|
||||
traps->top = top->y;
|
||||
traps->left.p1 = *top;
|
||||
traps->left.p2 = *left;
|
||||
traps->right.p1 = *top;
|
||||
traps->right.p2 = *right;
|
||||
|
||||
if (right->y < left->y)
|
||||
traps->bottom = right->y;
|
||||
else
|
||||
traps->bottom = left->y;
|
||||
|
||||
traps++;
|
||||
|
||||
*traps = *(traps - 1);
|
||||
|
||||
if (right->y < left->y)
|
||||
{
|
||||
traps->top = right->y;
|
||||
traps->bottom = left->y;
|
||||
traps->right.p1 = *right;
|
||||
traps->right.p2 = *left;
|
||||
}
|
||||
else
|
||||
{
|
||||
traps->top = left->y;
|
||||
traps->bottom = right->y;
|
||||
traps->left.p1 = *left;
|
||||
traps->left.p2 = *right;
|
||||
}
|
||||
}
|
||||
|
||||
static pixman_trapezoid_t *
|
||||
convert_triangles (int n_tris, const pixman_triangle_t *tris)
|
||||
{
|
||||
pixman_trapezoid_t *traps;
|
||||
int i;
|
||||
|
||||
if (n_tris <= 0)
|
||||
return NULL;
|
||||
|
||||
traps = pixman_malloc_ab (n_tris, 2 * sizeof (pixman_trapezoid_t));
|
||||
if (!traps)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < n_tris; ++i)
|
||||
triangle_to_trapezoids (&(tris[i]), traps + 2 * i);
|
||||
|
||||
return traps;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_composite_triangles (pixman_op_t op,
|
||||
pixman_image_t * src,
|
||||
pixman_image_t * dst,
|
||||
pixman_format_code_t mask_format,
|
||||
int x_src,
|
||||
int y_src,
|
||||
int x_dst,
|
||||
int y_dst,
|
||||
int n_tris,
|
||||
const pixman_triangle_t * tris)
|
||||
{
|
||||
pixman_trapezoid_t *traps;
|
||||
|
||||
if ((traps = convert_triangles (n_tris, tris)))
|
||||
{
|
||||
pixman_composite_trapezoids (op, src, dst, mask_format,
|
||||
x_src, y_src, x_dst, y_dst,
|
||||
n_tris * 2, traps);
|
||||
|
||||
free (traps);
|
||||
}
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_add_triangles (pixman_image_t *image,
|
||||
int32_t x_off,
|
||||
int32_t y_off,
|
||||
int n_tris,
|
||||
const pixman_triangle_t *tris)
|
||||
{
|
||||
pixman_trapezoid_t *traps;
|
||||
|
||||
if ((traps = convert_triangles (n_tris, tris)))
|
||||
{
|
||||
pixman_add_trapezoids (image, x_off, y_off,
|
||||
n_tris * 2, traps);
|
||||
|
||||
free (traps);
|
||||
}
|
||||
}
|
||||
315
gfx/cairo/libpixman/src/pixman-utils.c
Normal file
315
gfx/cairo/libpixman/src/pixman-utils.c
Normal file
|
|
@ -0,0 +1,315 @@
|
|||
/*
|
||||
* Copyright © 2000 SuSE, Inc.
|
||||
* Copyright © 1999 Keith Packard
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of SuSE not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. SuSE makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
|
||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Author: Keith Packard, SuSE, Inc.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "pixman-private.h"
|
||||
|
||||
pixman_bool_t
|
||||
_pixman_multiply_overflows_size (size_t a, size_t b)
|
||||
{
|
||||
return a >= SIZE_MAX / b;
|
||||
}
|
||||
|
||||
pixman_bool_t
|
||||
_pixman_multiply_overflows_int (unsigned int a, unsigned int b)
|
||||
{
|
||||
return a >= INT32_MAX / b;
|
||||
}
|
||||
|
||||
pixman_bool_t
|
||||
_pixman_addition_overflows_int (unsigned int a, unsigned int b)
|
||||
{
|
||||
return a > INT32_MAX - b;
|
||||
}
|
||||
|
||||
void *
|
||||
pixman_malloc_ab (unsigned int a,
|
||||
unsigned int b)
|
||||
{
|
||||
if (a >= INT32_MAX / b)
|
||||
return NULL;
|
||||
|
||||
return malloc (a * b);
|
||||
}
|
||||
|
||||
void *
|
||||
pixman_malloc_abc (unsigned int a,
|
||||
unsigned int b,
|
||||
unsigned int c)
|
||||
{
|
||||
if (a >= INT32_MAX / b)
|
||||
return NULL;
|
||||
else if (a * b >= INT32_MAX / c)
|
||||
return NULL;
|
||||
else
|
||||
return malloc (a * b * c);
|
||||
}
|
||||
|
||||
static force_inline uint16_t
|
||||
float_to_unorm (float f, int n_bits)
|
||||
{
|
||||
uint32_t u;
|
||||
|
||||
if (f > 1.0)
|
||||
f = 1.0;
|
||||
if (f < 0.0)
|
||||
f = 0.0;
|
||||
|
||||
u = f * (1 << n_bits);
|
||||
u -= (u >> n_bits);
|
||||
|
||||
return u;
|
||||
}
|
||||
|
||||
static force_inline float
|
||||
unorm_to_float (uint16_t u, int n_bits)
|
||||
{
|
||||
uint32_t m = ((1 << n_bits) - 1);
|
||||
|
||||
return (u & m) * (1.f / (float)m);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function expands images from a8r8g8b8 to argb_t. To preserve
|
||||
* precision, it needs to know from which source format the a8r8g8b8 pixels
|
||||
* originally came.
|
||||
*
|
||||
* For example, if the source was PIXMAN_x1r5g5b5 and the red component
|
||||
* contained bits 12345, then the 8-bit value is 12345123. To correctly
|
||||
* expand this to floating point, it should be 12345 / 31.0 and not
|
||||
* 12345123 / 255.0.
|
||||
*/
|
||||
void
|
||||
pixman_expand_to_float (argb_t *dst,
|
||||
const uint32_t *src,
|
||||
pixman_format_code_t format,
|
||||
int width)
|
||||
{
|
||||
static const float multipliers[16] = {
|
||||
0.0f,
|
||||
1.0f / ((1 << 1) - 1),
|
||||
1.0f / ((1 << 2) - 1),
|
||||
1.0f / ((1 << 3) - 1),
|
||||
1.0f / ((1 << 4) - 1),
|
||||
1.0f / ((1 << 5) - 1),
|
||||
1.0f / ((1 << 6) - 1),
|
||||
1.0f / ((1 << 7) - 1),
|
||||
1.0f / ((1 << 8) - 1),
|
||||
1.0f / ((1 << 9) - 1),
|
||||
1.0f / ((1 << 10) - 1),
|
||||
1.0f / ((1 << 11) - 1),
|
||||
1.0f / ((1 << 12) - 1),
|
||||
1.0f / ((1 << 13) - 1),
|
||||
1.0f / ((1 << 14) - 1),
|
||||
1.0f / ((1 << 15) - 1),
|
||||
};
|
||||
int a_size, r_size, g_size, b_size;
|
||||
int a_shift, r_shift, g_shift, b_shift;
|
||||
float a_mul, r_mul, g_mul, b_mul;
|
||||
uint32_t a_mask, r_mask, g_mask, b_mask;
|
||||
int i;
|
||||
|
||||
if (!PIXMAN_FORMAT_VIS (format))
|
||||
format = PIXMAN_a8r8g8b8;
|
||||
|
||||
/*
|
||||
* Determine the sizes of each component and the masks and shifts
|
||||
* required to extract them from the source pixel.
|
||||
*/
|
||||
a_size = PIXMAN_FORMAT_A (format);
|
||||
r_size = PIXMAN_FORMAT_R (format);
|
||||
g_size = PIXMAN_FORMAT_G (format);
|
||||
b_size = PIXMAN_FORMAT_B (format);
|
||||
|
||||
a_shift = 32 - a_size;
|
||||
r_shift = 24 - r_size;
|
||||
g_shift = 16 - g_size;
|
||||
b_shift = 8 - b_size;
|
||||
|
||||
a_mask = ((1 << a_size) - 1);
|
||||
r_mask = ((1 << r_size) - 1);
|
||||
g_mask = ((1 << g_size) - 1);
|
||||
b_mask = ((1 << b_size) - 1);
|
||||
|
||||
a_mul = multipliers[a_size];
|
||||
r_mul = multipliers[r_size];
|
||||
g_mul = multipliers[g_size];
|
||||
b_mul = multipliers[b_size];
|
||||
|
||||
/* Start at the end so that we can do the expansion in place
|
||||
* when src == dst
|
||||
*/
|
||||
for (i = width - 1; i >= 0; i--)
|
||||
{
|
||||
const uint32_t pixel = src[i];
|
||||
|
||||
dst[i].a = a_mask? ((pixel >> a_shift) & a_mask) * a_mul : 1.0f;
|
||||
dst[i].r = ((pixel >> r_shift) & r_mask) * r_mul;
|
||||
dst[i].g = ((pixel >> g_shift) & g_mask) * g_mul;
|
||||
dst[i].b = ((pixel >> b_shift) & b_mask) * b_mul;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t
|
||||
pixman_float_to_unorm (float f, int n_bits)
|
||||
{
|
||||
return float_to_unorm (f, n_bits);
|
||||
}
|
||||
|
||||
float
|
||||
pixman_unorm_to_float (uint16_t u, int n_bits)
|
||||
{
|
||||
return unorm_to_float (u, n_bits);
|
||||
}
|
||||
|
||||
void
|
||||
pixman_contract_from_float (uint32_t *dst,
|
||||
const argb_t *src,
|
||||
int width)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < width; ++i)
|
||||
{
|
||||
uint8_t a, r, g, b;
|
||||
|
||||
a = float_to_unorm (src[i].a, 8);
|
||||
r = float_to_unorm (src[i].r, 8);
|
||||
g = float_to_unorm (src[i].g, 8);
|
||||
b = float_to_unorm (src[i].b, 8);
|
||||
|
||||
dst[i] = (a << 24) | (r << 16) | (g << 8) | (b << 0);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t *
|
||||
_pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
return iter->buffer;
|
||||
}
|
||||
|
||||
#define N_TMP_BOXES (16)
|
||||
|
||||
pixman_bool_t
|
||||
pixman_region16_copy_from_region32 (pixman_region16_t *dst,
|
||||
pixman_region32_t *src)
|
||||
{
|
||||
int n_boxes, i;
|
||||
pixman_box32_t *boxes32;
|
||||
pixman_box16_t *boxes16;
|
||||
pixman_bool_t retval;
|
||||
|
||||
boxes32 = pixman_region32_rectangles (src, &n_boxes);
|
||||
|
||||
boxes16 = pixman_malloc_ab (n_boxes, sizeof (pixman_box16_t));
|
||||
|
||||
if (!boxes16)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < n_boxes; ++i)
|
||||
{
|
||||
boxes16[i].x1 = boxes32[i].x1;
|
||||
boxes16[i].y1 = boxes32[i].y1;
|
||||
boxes16[i].x2 = boxes32[i].x2;
|
||||
boxes16[i].y2 = boxes32[i].y2;
|
||||
}
|
||||
|
||||
pixman_region_fini (dst);
|
||||
retval = pixman_region_init_rects (dst, boxes16, n_boxes);
|
||||
free (boxes16);
|
||||
return retval;
|
||||
}
|
||||
|
||||
pixman_bool_t
|
||||
pixman_region32_copy_from_region16 (pixman_region32_t *dst,
|
||||
pixman_region16_t *src)
|
||||
{
|
||||
int n_boxes, i;
|
||||
pixman_box16_t *boxes16;
|
||||
pixman_box32_t *boxes32;
|
||||
pixman_box32_t tmp_boxes[N_TMP_BOXES];
|
||||
pixman_bool_t retval;
|
||||
|
||||
boxes16 = pixman_region_rectangles (src, &n_boxes);
|
||||
|
||||
if (n_boxes > N_TMP_BOXES)
|
||||
boxes32 = pixman_malloc_ab (n_boxes, sizeof (pixman_box32_t));
|
||||
else
|
||||
boxes32 = tmp_boxes;
|
||||
|
||||
if (!boxes32)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < n_boxes; ++i)
|
||||
{
|
||||
boxes32[i].x1 = boxes16[i].x1;
|
||||
boxes32[i].y1 = boxes16[i].y1;
|
||||
boxes32[i].x2 = boxes16[i].x2;
|
||||
boxes32[i].y2 = boxes16[i].y2;
|
||||
}
|
||||
|
||||
pixman_region32_fini (dst);
|
||||
retval = pixman_region32_init_rects (dst, boxes32, n_boxes);
|
||||
|
||||
if (boxes32 != tmp_boxes)
|
||||
free (boxes32);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* This function is exported for the sake of the test suite and not part
|
||||
* of the ABI.
|
||||
*/
|
||||
PIXMAN_EXPORT pixman_implementation_t *
|
||||
_pixman_internal_only_get_implementation (void)
|
||||
{
|
||||
return get_implementation ();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
void
|
||||
_pixman_log_error (const char *function, const char *message)
|
||||
{
|
||||
static int n_messages = 0;
|
||||
|
||||
if (n_messages < 10)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"*** BUG ***\n"
|
||||
"In %s: %s\n"
|
||||
"Set a breakpoint on '_pixman_log_error' to debug\n\n",
|
||||
function, message);
|
||||
|
||||
n_messages++;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
50
gfx/cairo/libpixman/src/pixman-version.h
Normal file
50
gfx/cairo/libpixman/src/pixman-version.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright © 2008 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Author: Carl D. Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#ifndef PIXMAN_VERSION_H__
|
||||
#define PIXMAN_VERSION_H__
|
||||
|
||||
#ifndef PIXMAN_H__
|
||||
# error pixman-version.h should only be included by pixman.h
|
||||
#endif
|
||||
|
||||
#define PIXMAN_VERSION_MAJOR 0
|
||||
#define PIXMAN_VERSION_MINOR 27
|
||||
#define PIXMAN_VERSION_MICRO 1
|
||||
|
||||
#define PIXMAN_VERSION_STRING "0.27.1"
|
||||
|
||||
#define PIXMAN_VERSION_ENCODE(major, minor, micro) ( \
|
||||
((major) * 10000) \
|
||||
+ ((minor) * 100) \
|
||||
+ ((micro) * 1))
|
||||
|
||||
#define PIXMAN_VERSION PIXMAN_VERSION_ENCODE( \
|
||||
PIXMAN_VERSION_MAJOR, \
|
||||
PIXMAN_VERSION_MINOR, \
|
||||
PIXMAN_VERSION_MICRO)
|
||||
|
||||
#endif /* PIXMAN_VERSION_H__ */
|
||||
1647
gfx/cairo/libpixman/src/pixman-vmx.c
Normal file
1647
gfx/cairo/libpixman/src/pixman-vmx.c
Normal file
File diff suppressed because it is too large
Load diff
263
gfx/cairo/libpixman/src/pixman-x64-mmx-emulation.h
Normal file
263
gfx/cairo/libpixman/src/pixman-x64-mmx-emulation.h
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
#ifndef MMX_X64_H_INCLUDED
|
||||
#define MMX_X64_H_INCLUDED
|
||||
|
||||
/* Implementation of x64 MMX substitition functions, before
|
||||
* pixman is reimplemented not to use __m64 type on Visual C++
|
||||
*
|
||||
* Copyright (C)2009 by George Yohng
|
||||
* Released in public domain.
|
||||
*/
|
||||
|
||||
#include <intrin.h>
|
||||
|
||||
#define M64C(a) (*(const __m64 *)(&a))
|
||||
#define M64U(a) (*(const unsigned long long *)(&a))
|
||||
|
||||
__inline __m64
|
||||
_m_from_int (int a)
|
||||
{
|
||||
long long i64 = a;
|
||||
|
||||
return M64C (i64);
|
||||
}
|
||||
|
||||
__inline __m64
|
||||
_mm_setzero_si64 ()
|
||||
{
|
||||
long long i64 = 0;
|
||||
|
||||
return M64C (i64);
|
||||
}
|
||||
|
||||
__inline __m64
|
||||
_mm_set_pi32 (int i1, int i0)
|
||||
{
|
||||
unsigned long long i64 = ((unsigned)i0) + (((unsigned long long)(unsigned)i1) << 32);
|
||||
|
||||
return M64C (i64);
|
||||
}
|
||||
|
||||
__inline void
|
||||
_m_empty ()
|
||||
{
|
||||
}
|
||||
|
||||
__inline __m64
|
||||
_mm_set1_pi16 (short w)
|
||||
{
|
||||
unsigned long long i64 = ((unsigned long long)(unsigned short)(w)) * 0x0001000100010001ULL;
|
||||
|
||||
return M64C (i64);
|
||||
}
|
||||
|
||||
__inline int
|
||||
_m_to_int (__m64 m)
|
||||
{
|
||||
return m.m64_i32[0];
|
||||
}
|
||||
|
||||
__inline __m64
|
||||
_mm_movepi64_pi64 (__m128i a)
|
||||
{
|
||||
return M64C (a.m128i_i64[0]);
|
||||
}
|
||||
|
||||
__inline __m64
|
||||
_m_pand (__m64 a, __m64 b)
|
||||
{
|
||||
unsigned long long i64 = M64U (a) & M64U (b);
|
||||
|
||||
return M64C (i64);
|
||||
}
|
||||
|
||||
__inline __m64
|
||||
_m_por (__m64 a, __m64 b)
|
||||
{
|
||||
unsigned long long i64 = M64U (a) | M64U (b);
|
||||
|
||||
return M64C (i64);
|
||||
}
|
||||
|
||||
__inline __m64
|
||||
_m_pxor (__m64 a, __m64 b)
|
||||
{
|
||||
unsigned long long i64 = M64U (a) ^ M64U (b);
|
||||
|
||||
return M64C (i64);
|
||||
}
|
||||
|
||||
__inline __m64
|
||||
_m_pmulhuw (__m64 a, __m64 b) /* unoptimized */
|
||||
{
|
||||
unsigned short d[4] =
|
||||
{
|
||||
(unsigned short)((((unsigned)a.m64_u16[0]) * b.m64_u16[0]) >> 16),
|
||||
(unsigned short)((((unsigned)a.m64_u16[1]) * b.m64_u16[1]) >> 16),
|
||||
(unsigned short)((((unsigned)a.m64_u16[2]) * b.m64_u16[2]) >> 16),
|
||||
(unsigned short)((((unsigned)a.m64_u16[3]) * b.m64_u16[3]) >> 16)
|
||||
};
|
||||
|
||||
return M64C (d[0]);
|
||||
}
|
||||
|
||||
__inline __m64
|
||||
_m_pmullw2 (__m64 a, __m64 b) /* unoptimized */
|
||||
{
|
||||
unsigned short d[4] =
|
||||
{
|
||||
(unsigned short)((((unsigned)a.m64_u16[0]) * b.m64_u16[0])),
|
||||
(unsigned short)((((unsigned)a.m64_u16[1]) * b.m64_u16[1])),
|
||||
(unsigned short)((((unsigned)a.m64_u16[2]) * b.m64_u16[2])),
|
||||
(unsigned short)((((unsigned)a.m64_u16[3]) * b.m64_u16[3]))
|
||||
};
|
||||
|
||||
return M64C (d[0]);
|
||||
}
|
||||
|
||||
__inline __m64
|
||||
_m_pmullw (__m64 a, __m64 b) /* unoptimized */
|
||||
{
|
||||
unsigned long long x =
|
||||
((unsigned long long)(unsigned short)((((unsigned)a.m64_u16[0]) * b.m64_u16[0]))) +
|
||||
(((unsigned long long)(unsigned short)((((unsigned)a.m64_u16[1]) * b.m64_u16[1]))) << 16) +
|
||||
(((unsigned long long)(unsigned short)((((unsigned)a.m64_u16[2]) * b.m64_u16[2]))) << 32) +
|
||||
(((unsigned long long)(unsigned short)((((unsigned)a.m64_u16[3]) * b.m64_u16[3]))) << 48);
|
||||
|
||||
return M64C (x);
|
||||
}
|
||||
|
||||
__inline __m64
|
||||
_m_paddusb (__m64 a, __m64 b) /* unoptimized */
|
||||
{
|
||||
unsigned long long x = (M64U (a) & 0x00FF00FF00FF00FFULL) +
|
||||
(M64U (b) & 0x00FF00FF00FF00FFULL);
|
||||
|
||||
unsigned long long y = ((M64U (a) >> 8) & 0x00FF00FF00FF00FFULL) +
|
||||
((M64U (b) >> 8) & 0x00FF00FF00FF00FFULL);
|
||||
|
||||
x |= ((x & 0xFF00FF00FF00FF00ULL) >> 8) * 0xFF;
|
||||
y |= ((y & 0xFF00FF00FF00FF00ULL) >> 8) * 0xFF;
|
||||
|
||||
x = (x & 0x00FF00FF00FF00FFULL) | ((y & 0x00FF00FF00FF00FFULL) << 8);
|
||||
|
||||
return M64C (x);
|
||||
}
|
||||
|
||||
__inline __m64
|
||||
_m_paddusw (__m64 a, __m64 b) /* unoptimized */
|
||||
{
|
||||
unsigned long long x = (M64U (a) & 0x0000FFFF0000FFFFULL) +
|
||||
(M64U (b) & 0x0000FFFF0000FFFFULL);
|
||||
|
||||
unsigned long long y = ((M64U (a) >> 16) & 0x0000FFFF0000FFFFULL) +
|
||||
((M64U (b) >> 16) & 0x0000FFFF0000FFFFULL);
|
||||
|
||||
x |= ((x & 0xFFFF0000FFFF0000) >> 16) * 0xFFFF;
|
||||
y |= ((y & 0xFFFF0000FFFF0000) >> 16) * 0xFFFF;
|
||||
|
||||
x = (x & 0x0000FFFF0000FFFFULL) | ((y & 0x0000FFFF0000FFFFULL) << 16);
|
||||
|
||||
return M64C (x);
|
||||
}
|
||||
|
||||
__inline __m64
|
||||
_m_pshufw (__m64 a, int n) /* unoptimized */
|
||||
{
|
||||
unsigned short d[4] =
|
||||
{
|
||||
a.m64_u16[n & 3],
|
||||
a.m64_u16[(n >> 2) & 3],
|
||||
a.m64_u16[(n >> 4) & 3],
|
||||
a.m64_u16[(n >> 6) & 3]
|
||||
};
|
||||
|
||||
return M64C (d[0]);
|
||||
}
|
||||
|
||||
__inline unsigned char
|
||||
sat16 (unsigned short d)
|
||||
{
|
||||
if (d > 0xFF) return 0xFF;
|
||||
else return d & 0xFF;
|
||||
}
|
||||
|
||||
__inline __m64
|
||||
_m_packuswb (__m64 m1, __m64 m2) /* unoptimized */
|
||||
{
|
||||
unsigned char d[8] =
|
||||
{
|
||||
sat16 (m1.m64_u16[0]),
|
||||
sat16 (m1.m64_u16[1]),
|
||||
sat16 (m1.m64_u16[2]),
|
||||
sat16 (m1.m64_u16[3]),
|
||||
sat16 (m2.m64_u16[0]),
|
||||
sat16 (m2.m64_u16[1]),
|
||||
sat16 (m2.m64_u16[2]),
|
||||
sat16 (m2.m64_u16[3])
|
||||
};
|
||||
|
||||
return M64C (d[0]);
|
||||
}
|
||||
|
||||
__inline __m64 _m_punpcklbw (__m64 m1, __m64 m2) /* unoptimized */
|
||||
{
|
||||
unsigned char d[8] =
|
||||
{
|
||||
m1.m64_u8[0],
|
||||
m2.m64_u8[0],
|
||||
m1.m64_u8[1],
|
||||
m2.m64_u8[1],
|
||||
m1.m64_u8[2],
|
||||
m2.m64_u8[2],
|
||||
m1.m64_u8[3],
|
||||
m2.m64_u8[3],
|
||||
};
|
||||
|
||||
return M64C (d[0]);
|
||||
}
|
||||
|
||||
__inline __m64 _m_punpckhbw (__m64 m1, __m64 m2) /* unoptimized */
|
||||
{
|
||||
unsigned char d[8] =
|
||||
{
|
||||
m1.m64_u8[4],
|
||||
m2.m64_u8[4],
|
||||
m1.m64_u8[5],
|
||||
m2.m64_u8[5],
|
||||
m1.m64_u8[6],
|
||||
m2.m64_u8[6],
|
||||
m1.m64_u8[7],
|
||||
m2.m64_u8[7],
|
||||
};
|
||||
|
||||
return M64C (d[0]);
|
||||
}
|
||||
|
||||
__inline __m64 _m_psrlwi (__m64 a, int n) /* unoptimized */
|
||||
{
|
||||
unsigned short d[4] =
|
||||
{
|
||||
a.m64_u16[0] >> n,
|
||||
a.m64_u16[1] >> n,
|
||||
a.m64_u16[2] >> n,
|
||||
a.m64_u16[3] >> n
|
||||
};
|
||||
|
||||
return M64C (d[0]);
|
||||
}
|
||||
|
||||
__inline __m64 _m_psrlqi (__m64 m, int n)
|
||||
{
|
||||
unsigned long long x = M64U (m) >> n;
|
||||
|
||||
return M64C (x);
|
||||
}
|
||||
|
||||
__inline __m64 _m_psllqi (__m64 m, int n)
|
||||
{
|
||||
unsigned long long x = M64U (m) << n;
|
||||
|
||||
return M64C (x);
|
||||
}
|
||||
|
||||
#endif /* MMX_X64_H_INCLUDED */
|
||||
241
gfx/cairo/libpixman/src/pixman-x86.c
Normal file
241
gfx/cairo/libpixman/src/pixman-x86.c
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
* Copyright © 2000 SuSE, Inc.
|
||||
* Copyright © 2007 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of SuSE not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. SuSE makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
|
||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "pixman-private.h"
|
||||
|
||||
#if defined(USE_X86_MMX) || defined (USE_SSE2)
|
||||
|
||||
/* The CPU detection code needs to be in a file not compiled with
|
||||
* "-mmmx -msse", as gcc would generate CMOV instructions otherwise
|
||||
* that would lead to SIGILL instructions on old CPUs that don't have
|
||||
* it.
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
X86_MMX = (1 << 0),
|
||||
X86_MMX_EXTENSIONS = (1 << 1),
|
||||
X86_SSE = (1 << 2) | X86_MMX_EXTENSIONS,
|
||||
X86_SSE2 = (1 << 3),
|
||||
X86_CMOV = (1 << 4)
|
||||
} cpu_features_t;
|
||||
|
||||
#ifdef HAVE_GETISAX
|
||||
|
||||
#include <sys/auxv.h>
|
||||
|
||||
static cpu_features_t
|
||||
detect_cpu_features (void)
|
||||
{
|
||||
cpu_features_t features = 0;
|
||||
unsigned int result = 0;
|
||||
|
||||
if (getisax (&result, 1))
|
||||
{
|
||||
if (result & AV_386_CMOV)
|
||||
features |= X86_CMOV;
|
||||
if (result & AV_386_MMX)
|
||||
features |= X86_MMX;
|
||||
if (result & AV_386_AMD_MMX)
|
||||
features |= X86_MMX_EXTENSIONS;
|
||||
if (result & AV_386_SSE)
|
||||
features |= X86_SSE;
|
||||
if (result & AV_386_SSE2)
|
||||
features |= X86_SSE2;
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define _PIXMAN_X86_64 \
|
||||
(defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64))
|
||||
|
||||
static pixman_bool_t
|
||||
have_cpuid (void)
|
||||
{
|
||||
#if _PIXMAN_X86_64 || defined (_MSC_VER)
|
||||
|
||||
return TRUE;
|
||||
|
||||
#elif defined (__GNUC__)
|
||||
uint32_t result;
|
||||
|
||||
__asm__ volatile (
|
||||
"pushf" "\n\t"
|
||||
"pop %%eax" "\n\t"
|
||||
"mov %%eax, %%ecx" "\n\t"
|
||||
"xor $0x00200000, %%eax" "\n\t"
|
||||
"push %%eax" "\n\t"
|
||||
"popf" "\n\t"
|
||||
"pushf" "\n\t"
|
||||
"pop %%eax" "\n\t"
|
||||
"xor %%ecx, %%eax" "\n\t"
|
||||
"mov %%eax, %0" "\n\t"
|
||||
: "=r" (result)
|
||||
:
|
||||
: "%eax", "%ecx");
|
||||
|
||||
return !!result;
|
||||
|
||||
#else
|
||||
#error "Unknown compiler"
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <intrin.h> /* for __cpuid */
|
||||
#endif
|
||||
|
||||
static void
|
||||
pixman_cpuid (uint32_t feature,
|
||||
uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d)
|
||||
{
|
||||
#if defined (__GNUC__)
|
||||
|
||||
#if _PIXMAN_X86_64
|
||||
__asm__ volatile (
|
||||
"cpuid" "\n\t"
|
||||
: "=a" (*a), "=b" (*b), "=c" (*c), "=d" (*d)
|
||||
: "a" (feature));
|
||||
#else
|
||||
/* On x86-32 we need to be careful about the handling of %ebx
|
||||
* and %esp. We can't declare either one as clobbered
|
||||
* since they are special registers (%ebx is the "PIC
|
||||
* register" holding an offset to global data, %esp the
|
||||
* stack pointer), so we need to make sure that %ebx is
|
||||
* preserved, and that %esp has its original value when
|
||||
* accessing the output operands.
|
||||
*/
|
||||
__asm__ volatile (
|
||||
"xchg %%ebx, %1" "\n\t"
|
||||
"cpuid" "\n\t"
|
||||
"xchg %%ebx, %1" "\n\t"
|
||||
: "=a" (*a), "=r" (*b), "=c" (*c), "=d" (*d)
|
||||
: "a" (feature));
|
||||
#endif
|
||||
|
||||
#elif defined (_MSC_VER)
|
||||
int info[4];
|
||||
|
||||
__cpuid (info, feature);
|
||||
|
||||
*a = info[0];
|
||||
*b = info[1];
|
||||
*c = info[2];
|
||||
*d = info[3];
|
||||
#else
|
||||
#error Unknown compiler
|
||||
#endif
|
||||
}
|
||||
|
||||
static cpu_features_t
|
||||
detect_cpu_features (void)
|
||||
{
|
||||
uint32_t a, b, c, d;
|
||||
cpu_features_t features = 0;
|
||||
|
||||
if (!have_cpuid())
|
||||
return features;
|
||||
|
||||
/* Get feature bits */
|
||||
pixman_cpuid (0x01, &a, &b, &c, &d);
|
||||
if (d & (1 << 15))
|
||||
features |= X86_CMOV;
|
||||
if (d & (1 << 23))
|
||||
features |= X86_MMX;
|
||||
if (d & (1 << 25))
|
||||
features |= X86_SSE;
|
||||
if (d & (1 << 26))
|
||||
features |= X86_SSE2;
|
||||
|
||||
/* Check for AMD specific features */
|
||||
if ((features & X86_MMX) && !(features & X86_SSE))
|
||||
{
|
||||
char vendor[13];
|
||||
|
||||
/* Get vendor string */
|
||||
memset (vendor, 0, sizeof vendor);
|
||||
|
||||
pixman_cpuid (0x00, &a, &b, &c, &d);
|
||||
memcpy (vendor + 0, &b, 4);
|
||||
memcpy (vendor + 4, &d, 4);
|
||||
memcpy (vendor + 8, &c, 4);
|
||||
|
||||
if (strcmp (vendor, "AuthenticAMD") == 0 ||
|
||||
strcmp (vendor, "Geode by NSC") == 0)
|
||||
{
|
||||
pixman_cpuid (0x80000000, &a, &b, &c, &d);
|
||||
if (a >= 0x80000001)
|
||||
{
|
||||
pixman_cpuid (0x80000001, &a, &b, &c, &d);
|
||||
|
||||
if (d & (1 << 22))
|
||||
features |= X86_MMX_EXTENSIONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static pixman_bool_t
|
||||
have_feature (cpu_features_t feature)
|
||||
{
|
||||
static pixman_bool_t initialized;
|
||||
static cpu_features_t features;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
features = detect_cpu_features();
|
||||
initialized = TRUE;
|
||||
}
|
||||
|
||||
return (features & feature) == feature;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
pixman_implementation_t *
|
||||
_pixman_x86_get_implementations (pixman_implementation_t *imp)
|
||||
{
|
||||
#define MMX_BITS (X86_MMX | X86_MMX_EXTENSIONS)
|
||||
#define SSE2_BITS (X86_MMX | X86_MMX_EXTENSIONS | X86_SSE | X86_SSE2)
|
||||
|
||||
#ifdef USE_X86_MMX
|
||||
if (!_pixman_disabled ("mmx") && have_feature (MMX_BITS))
|
||||
imp = _pixman_implementation_create_mmx (imp);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SSE2
|
||||
if (!_pixman_disabled ("sse2") && have_feature (SSE2_BITS))
|
||||
imp = _pixman_implementation_create_sse2 (imp);
|
||||
#endif
|
||||
|
||||
return imp;
|
||||
}
|
||||
1135
gfx/cairo/libpixman/src/pixman.c
Normal file
1135
gfx/cairo/libpixman/src/pixman.c
Normal file
File diff suppressed because it is too large
Load diff
1116
gfx/cairo/libpixman/src/pixman.h
Normal file
1116
gfx/cairo/libpixman/src/pixman.h
Normal file
File diff suppressed because it is too large
Load diff
478
gfx/cairo/libpixman/src/refactor
Normal file
478
gfx/cairo/libpixman/src/refactor
Normal file
|
|
@ -0,0 +1,478 @@
|
|||
Roadmap
|
||||
|
||||
- Move all the fetchers etc. into pixman-image to make pixman-compose.c
|
||||
less intimidating.
|
||||
|
||||
DONE
|
||||
|
||||
- Make combiners for unified alpha take a mask argument. That way
|
||||
we won't need two separate paths for unified vs component in the
|
||||
general compositing code.
|
||||
|
||||
DONE, except that the Altivec code needs to be updated. Luca is
|
||||
looking into that.
|
||||
|
||||
- Delete separate 'unified alpha' path
|
||||
|
||||
DONE
|
||||
|
||||
- Split images into their own files
|
||||
|
||||
DONE
|
||||
|
||||
- Split the gradient walker code out into its own file
|
||||
|
||||
DONE
|
||||
|
||||
- Add scanline getters per image
|
||||
|
||||
DONE
|
||||
|
||||
- Generic 64 bit fetcher
|
||||
|
||||
DONE
|
||||
|
||||
- Split fast path tables into their respective architecture dependent
|
||||
files.
|
||||
|
||||
See "Render Algorithm" below for rationale
|
||||
|
||||
Images will eventually have these virtual functions:
|
||||
|
||||
get_scanline()
|
||||
get_scanline_wide()
|
||||
get_pixel()
|
||||
get_pixel_wide()
|
||||
get_untransformed_pixel()
|
||||
get_untransformed_pixel_wide()
|
||||
get_unfiltered_pixel()
|
||||
get_unfiltered_pixel_wide()
|
||||
|
||||
store_scanline()
|
||||
store_scanline_wide()
|
||||
|
||||
1.
|
||||
|
||||
Initially we will just have get_scanline() and get_scanline_wide();
|
||||
these will be based on the ones in pixman-compose. Hopefully this will
|
||||
reduce the complexity in pixman_composite_rect_general().
|
||||
|
||||
Note that there is access considerations - the compose function is
|
||||
being compiled twice.
|
||||
|
||||
|
||||
2.
|
||||
|
||||
Split image types into their own source files. Export noop virtual
|
||||
reinit() call. Call this whenever a property of the image changes.
|
||||
|
||||
|
||||
3.
|
||||
|
||||
Split the get_scanline() call into smaller functions that are
|
||||
initialized by the reinit() call.
|
||||
|
||||
The Render Algorithm:
|
||||
(first repeat, then filter, then transform, then clip)
|
||||
|
||||
Starting from a destination pixel (x, y), do
|
||||
|
||||
1 x = x - xDst + xSrc
|
||||
y = y - yDst + ySrc
|
||||
|
||||
2 reject pixel that is outside the clip
|
||||
|
||||
This treats clipping as something that happens after
|
||||
transformation, which I think is correct for client clips. For
|
||||
hierarchy clips it is wrong, but who really cares? Without
|
||||
GraphicsExposes hierarchy clips are basically irrelevant. Yes,
|
||||
you could imagine cases where the pixels of a subwindow of a
|
||||
redirected, transformed window should be treated as
|
||||
transparent. I don't really care
|
||||
|
||||
Basically, I think the render spec should say that pixels that
|
||||
are unavailable due to the hierarcy have undefined content,
|
||||
and that GraphicsExposes are not generated. Ie., basically
|
||||
that using non-redirected windows as sources is fail. This is
|
||||
at least consistent with the current implementation and we can
|
||||
update the spec later if someone makes it work.
|
||||
|
||||
The implication for render is that it should stop passing the
|
||||
hierarchy clip to pixman. In pixman, if a souce image has a
|
||||
clip it should be used in computing the composite region and
|
||||
nowhere else, regardless of what "has_client_clip" says. The
|
||||
default should be for there to not be any clip.
|
||||
|
||||
I would really like to get rid of the client clip as well for
|
||||
source images, but unfortunately there is at least one
|
||||
application in the wild that uses them.
|
||||
|
||||
3 Transform pixel: (x, y) = T(x, y)
|
||||
|
||||
4 Call p = GetUntransformedPixel (x, y)
|
||||
|
||||
5 If the image has an alpha map, then
|
||||
|
||||
Call GetUntransformedPixel (x, y) on the alpha map
|
||||
|
||||
add resulting alpha channel to p
|
||||
|
||||
return p
|
||||
|
||||
Where GetUnTransformedPixel is:
|
||||
|
||||
6 switch (filter)
|
||||
{
|
||||
case NEAREST:
|
||||
return GetUnfilteredPixel (x, y);
|
||||
break;
|
||||
|
||||
case BILINEAR:
|
||||
return GetUnfilteredPixel (...) // 4 times
|
||||
break;
|
||||
|
||||
case CONVOLUTION:
|
||||
return GetUnfilteredPixel (...) // as many times as necessary.
|
||||
break;
|
||||
}
|
||||
|
||||
Where GetUnfilteredPixel (x, y) is
|
||||
|
||||
7 switch (repeat)
|
||||
{
|
||||
case REPEAT_NORMAL:
|
||||
case REPEAT_PAD:
|
||||
case REPEAT_REFLECT:
|
||||
// adjust x, y as appropriate
|
||||
break;
|
||||
|
||||
case REPEAT_NONE:
|
||||
if (x, y) is outside image bounds
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return GetRawPixel(x, y)
|
||||
|
||||
Where GetRawPixel (x, y) is
|
||||
|
||||
8 Compute the pixel in question, depending on image type.
|
||||
|
||||
For gradients, repeat has a totally different meaning, so
|
||||
UnfilteredPixel() and RawPixel() must be the same function so that
|
||||
gradients can do their own repeat algorithm.
|
||||
|
||||
So, the GetRawPixel
|
||||
|
||||
for bits must deal with repeats
|
||||
for gradients must deal with repeats (differently)
|
||||
for solids, should ignore repeats.
|
||||
|
||||
for polygons, when we add them, either ignore repeats or do
|
||||
something similar to bits (in which case, we may want an extra
|
||||
layer of indirection to modify the coordinates).
|
||||
|
||||
It is then possible to build things like "get scanline" or "get tile" on
|
||||
top of this. In the simplest case, just repeatedly calling GetPixel()
|
||||
would work, but specialized get_scanline()s or get_tile()s could be
|
||||
plugged in for common cases.
|
||||
|
||||
By not plugging anything in for images with access functions, we only
|
||||
have to compile the pixel functions twice, not the scanline functions.
|
||||
|
||||
And we can get rid of fetchers for the bizarre formats that no one
|
||||
uses. Such as b2g3r3 etc. r1g2b1? Seriously? It is also worth
|
||||
considering a generic format based pixel fetcher for these edge cases.
|
||||
|
||||
Since the actual routines depend on the image attributes, the images
|
||||
must be notified when those change and update their function pointers
|
||||
appropriately. So there should probably be a virtual function called
|
||||
(* reinit) or something like that.
|
||||
|
||||
There will also be wide fetchers for both pixels and lines. The line
|
||||
fetcher will just call the wide pixel fetcher. The wide pixel fetcher
|
||||
will just call expand, except for 10 bit formats.
|
||||
|
||||
Rendering pipeline:
|
||||
|
||||
Drawable:
|
||||
0. if (picture has alpha map)
|
||||
0.1. Position alpha map according to the alpha_x/alpha_y
|
||||
0.2. Where the two drawables intersect, the alpha channel
|
||||
Replace the alpha channel of source with the one
|
||||
from the alpha map. Replacement only takes place
|
||||
in the intersection of the two drawables' geometries.
|
||||
1. Repeat the drawable according to the repeat attribute
|
||||
2. Reconstruct a continuous image according to the filter
|
||||
3. Transform according to the transform attribute
|
||||
4. Position image such that src_x, src_y is over dst_x, dst_y
|
||||
5. Sample once per destination pixel
|
||||
6. Clip. If a pixel is not within the source clip, then no
|
||||
compositing takes place at that pixel. (Ie., it's *not*
|
||||
treated as 0).
|
||||
|
||||
Sampling a drawable:
|
||||
|
||||
- If the channel does not have an alpha channel, the pixels in it
|
||||
are treated as opaque.
|
||||
|
||||
Note on reconstruction:
|
||||
|
||||
- The top left pixel has coordinates (0.5, 0.5) and pixels are
|
||||
spaced 1 apart.
|
||||
|
||||
Gradient:
|
||||
1. Unless gradient type is conical, repeat the underlying (0, 1)
|
||||
gradient according to the repeat attribute
|
||||
2. Integrate the gradient across the plane according to type.
|
||||
3. Transform according to transform attribute
|
||||
4. Position gradient
|
||||
5. Sample once per destination pixel.
|
||||
6. Clip
|
||||
|
||||
Solid Fill:
|
||||
1. Repeat has no effect
|
||||
2. Image is already continuous and defined for the entire plane
|
||||
3. Transform has no effect
|
||||
4. Positioning has no effect
|
||||
5. Sample once per destination pixel.
|
||||
6. Clip
|
||||
|
||||
Polygon:
|
||||
1. Repeat has no effect
|
||||
2. Image is already continuous and defined on the whole plane
|
||||
3. Transform according to transform attribute
|
||||
4. Position image
|
||||
5. Supersample 15x17 per destination pixel.
|
||||
6. Clip
|
||||
|
||||
Possibly interesting additions:
|
||||
- More general transformations, such as warping, or general
|
||||
shading.
|
||||
|
||||
- Shader image where a function is called to generate the
|
||||
pixel (ie., uploading assembly code).
|
||||
|
||||
- Resampling kernels
|
||||
|
||||
In principle the polygon image uses a 15x17 box filter for
|
||||
resampling. If we allow general resampling filters, then we
|
||||
get all the various antialiasing types for free.
|
||||
|
||||
Bilinear downsampling looks terrible and could be much
|
||||
improved by a resampling filter. NEAREST reconstruction
|
||||
combined with a box resampling filter is what GdkPixbuf
|
||||
does, I believe.
|
||||
|
||||
Useful for high frequency gradients as well.
|
||||
|
||||
(Note that the difference between a reconstruction and a
|
||||
resampling filter is mainly where in the pipeline they
|
||||
occur. High quality resampling should use a correctly
|
||||
oriented kernel so it should happen after transformation.
|
||||
|
||||
An implementation can transform the resampling kernel and
|
||||
convolve it with the reconstruction if it so desires, but it
|
||||
will need to deal with the fact that the resampling kernel
|
||||
will not necessarily be pixel aligned.
|
||||
|
||||
"Output kernels"
|
||||
|
||||
One could imagine doing the resampling after compositing,
|
||||
ie., for each destination pixel sample each source image 16
|
||||
times, then composite those subpixels individually, then
|
||||
finally apply a kernel.
|
||||
|
||||
However, this is effectively the same as full screen
|
||||
antialiasing, which is a simpler way to think about it. So
|
||||
resampling kernels may make sense for individual images, but
|
||||
not as a post-compositing step.
|
||||
|
||||
Fullscreen AA is inefficient without chained compositing
|
||||
though. Consider an (image scaled up to oversample size IN
|
||||
some polygon) scaled down to screen size. With the current
|
||||
implementation, there will be a huge temporary. With chained
|
||||
compositing, the whole thing ends up being equivalent to the
|
||||
output kernel from above.
|
||||
|
||||
- Color space conversion
|
||||
|
||||
The complete model here is that each surface has a color
|
||||
space associated with it and that the compositing operation
|
||||
also has one associated with it. Note also that gradients
|
||||
should have associcated colorspaces.
|
||||
|
||||
- Dithering
|
||||
|
||||
If people dither something that is already dithered, it will
|
||||
look terrible, but don't do that, then. (Dithering happens
|
||||
after resampling if at all - what is the relationship
|
||||
with color spaces? Presumably dithering should happen in linear
|
||||
intensity space).
|
||||
|
||||
- Floating point surfaces, 16, 32 and possibly 64 bit per
|
||||
channel.
|
||||
|
||||
Maybe crack:
|
||||
|
||||
- Glyph polygons
|
||||
|
||||
If glyphs could be given as polygons, they could be
|
||||
positioned and rasterized more accurately. The glyph
|
||||
structure would need subpixel positioning though.
|
||||
|
||||
- Luminance vs. coverage for the alpha channel
|
||||
|
||||
Whether the alpha channel should be interpreted as luminance
|
||||
modulation or as coverage (intensity modulation). This is a
|
||||
bit of a departure from the rendering model though. It could
|
||||
also be considered whether it should be possible to have
|
||||
both channels in the same drawable.
|
||||
|
||||
- Alternative for component alpha
|
||||
|
||||
- Set component-alpha on the output image.
|
||||
|
||||
- This means each of the components are sampled
|
||||
independently and composited in the corresponding
|
||||
channel only.
|
||||
|
||||
- Have 3 x oversampled mask
|
||||
|
||||
- Scale it down by 3 horizontally, with [ 1/3, 1/3, 1/3 ]
|
||||
resampling filter.
|
||||
|
||||
Is this equivalent to just using a component alpha mask?
|
||||
|
||||
Incompatible changes:
|
||||
|
||||
- Gradients could be specified with premultiplied colors. (You
|
||||
can use a mask to get things like gradients from solid red to
|
||||
transparent red.
|
||||
|
||||
Refactoring pixman
|
||||
|
||||
The pixman code is not particularly nice to put it mildly. Among the
|
||||
issues are
|
||||
|
||||
- inconsistent naming style (fb vs Fb, camelCase vs
|
||||
underscore_naming). Sometimes there is even inconsistency *within*
|
||||
one name.
|
||||
|
||||
fetchProc32 ACCESS(pixman_fetchProcForPicture32)
|
||||
|
||||
may be one of the uglies names ever created.
|
||||
|
||||
coding style:
|
||||
use the one from cairo except that pixman uses this brace style:
|
||||
|
||||
while (blah)
|
||||
{
|
||||
}
|
||||
|
||||
Format do while like this:
|
||||
|
||||
do
|
||||
{
|
||||
|
||||
}
|
||||
while (...);
|
||||
|
||||
- PIXMAN_COMPOSITE_RECT_GENERAL() is horribly complex
|
||||
|
||||
- switch case logic in pixman-access.c
|
||||
|
||||
Instead it would be better to just store function pointers in the
|
||||
image objects themselves,
|
||||
|
||||
get_pixel()
|
||||
get_scanline()
|
||||
|
||||
- Much of the scanline fetching code is for formats that no one
|
||||
ever uses. a2r2g2b2 anyone?
|
||||
|
||||
It would probably be worthwhile having a generic fetcher for any
|
||||
pixman format whatsoever.
|
||||
|
||||
- Code related to particular image types should be split into individual
|
||||
files.
|
||||
|
||||
pixman-bits-image.c
|
||||
pixman-linear-gradient-image.c
|
||||
pixman-radial-gradient-image.c
|
||||
pixman-solid-image.c
|
||||
|
||||
- Fast path code should be split into files based on architecture:
|
||||
|
||||
pixman-mmx-fastpath.c
|
||||
pixman-sse2-fastpath.c
|
||||
pixman-c-fastpath.c
|
||||
|
||||
etc.
|
||||
|
||||
Each of these files should then export a fastpath table, which would
|
||||
be declared in pixman-private.h. This should allow us to get rid
|
||||
of the pixman-mmx.h files.
|
||||
|
||||
The fast path table should describe each fast path. Ie there should
|
||||
be bitfields indicating what things the fast path can handle, rather than
|
||||
like now where it is only allowed to take one format per src/mask/dest. Ie.,
|
||||
|
||||
{
|
||||
FAST_a8r8g8b8 | FAST_x8r8g8b8,
|
||||
FAST_null,
|
||||
FAST_x8r8g8b8,
|
||||
FAST_repeat_normal | FAST_repeat_none,
|
||||
the_fast_path
|
||||
}
|
||||
|
||||
There should then be *one* file that implements pixman_image_composite().
|
||||
This should do this:
|
||||
|
||||
optimize_operator();
|
||||
|
||||
convert 1x1 repeat to solid (actually this should be done at
|
||||
image creation time).
|
||||
|
||||
is there a useful fastpath?
|
||||
|
||||
There should be a file called pixman-cpu.c that contains all the
|
||||
architecture specific stuff to detect what CPU features we have.
|
||||
|
||||
Issues that must be kept in mind:
|
||||
|
||||
- we need accessor code to be preserved
|
||||
|
||||
- maybe there should be a "store_scanline" too?
|
||||
|
||||
Is this sufficient?
|
||||
|
||||
We should preserve the optimization where the
|
||||
compositing happens directly in the destination
|
||||
whenever possible.
|
||||
|
||||
- It should be possible to create GPU samplers from the
|
||||
images.
|
||||
|
||||
The "horizontal" classification should be a bit in the image, the
|
||||
"vertical" classification should just happen inside the gradient
|
||||
file. Note though that
|
||||
|
||||
(a) these will change if the tranformation/repeat changes.
|
||||
|
||||
(b) at the moment the optimization for linear gradients
|
||||
takes the source rectangle into account. Presumably
|
||||
this is to also optimize the case where the gradient
|
||||
is close enough to horizontal?
|
||||
|
||||
Who is responsible for repeats? In principle it should be the scanline
|
||||
fetch. Right now NORMAL repeats are handled by walk_composite_region()
|
||||
while other repeats are handled by the scanline code.
|
||||
|
||||
|
||||
(Random note on filtering: do you filter before or after
|
||||
transformation? Hardware is going to filter after transformation;
|
||||
this is also what pixman does currently). It's not completely clear
|
||||
what filtering *after* transformation means. One thing that might look
|
||||
good would be to do *supersampling*, ie., compute multiple subpixels
|
||||
per destination pixel, then average them together.
|
||||
Loading…
Add table
Add a link
Reference in a new issue