forked from KolibriOS/kolibrios
pixman-0.30.2
git-svn-id: svn://kolibrios.org@3931 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
4e370891be
commit
40a47213e6
148
programs/develop/libraries/newlib/sdk/fasm/include/pixman-1.inc
Normal file
148
programs/develop/libraries/newlib/sdk/fasm/include/pixman-1.inc
Normal file
@ -0,0 +1,148 @@
|
||||
import pixman-1,\
|
||||
_pixman_internal_only_get_implementation,'_pixman_internal_only_get_implementation',\
|
||||
pixman_add_trapezoids,'pixman_add_trapezoids',\
|
||||
pixman_add_traps,'pixman_add_traps',\
|
||||
pixman_add_triangles,'pixman_add_triangles',\
|
||||
pixman_blt,'pixman_blt',\
|
||||
pixman_composite_glyphs,'pixman_composite_glyphs',\
|
||||
pixman_composite_glyphs_no_mask,'pixman_composite_glyphs_no_mask',\
|
||||
pixman_composite_trapezoids,'pixman_composite_trapezoids',\
|
||||
pixman_composite_triangles,'pixman_composite_triangles',\
|
||||
pixman_compute_composite_region,'pixman_compute_composite_region',\
|
||||
pixman_disable_out_of_bounds_workaround,'pixman_disable_out_of_bounds_workaround',\
|
||||
pixman_edge_init,'pixman_edge_init',\
|
||||
pixman_edge_step,'pixman_edge_step',\
|
||||
pixman_f_transform_bounds,'pixman_f_transform_bounds',\
|
||||
pixman_f_transform_from_pixman_transform,'pixman_f_transform_from_pixman_transform',\
|
||||
pixman_f_transform_init_identity,'pixman_f_transform_init_identity',\
|
||||
pixman_f_transform_init_rotate,'pixman_f_transform_init_rotate',\
|
||||
pixman_f_transform_init_scale,'pixman_f_transform_init_scale',\
|
||||
pixman_f_transform_init_translate,'pixman_f_transform_init_translate',\
|
||||
pixman_f_transform_invert,'pixman_f_transform_invert',\
|
||||
pixman_f_transform_multiply,'pixman_f_transform_multiply',\
|
||||
pixman_f_transform_point,'pixman_f_transform_point',\
|
||||
pixman_f_transform_point_3d,'pixman_f_transform_point_3d',\
|
||||
pixman_f_transform_rotate,'pixman_f_transform_rotate',\
|
||||
pixman_f_transform_scale,'pixman_f_transform_scale',\
|
||||
pixman_f_transform_translate,'pixman_f_transform_translate',\
|
||||
pixman_fill,'pixman_fill',\
|
||||
pixman_filter_create_separable_convolution,'pixman_filter_create_separable_convolution',\
|
||||
pixman_format_supported_destination,'pixman_format_supported_destination',\
|
||||
pixman_format_supported_source,'pixman_format_supported_source',\
|
||||
pixman_glyph_cache_create,'pixman_glyph_cache_create',\
|
||||
pixman_glyph_cache_destroy,'pixman_glyph_cache_destroy',\
|
||||
pixman_glyph_cache_freeze,'pixman_glyph_cache_freeze',\
|
||||
pixman_glyph_cache_insert,'pixman_glyph_cache_insert',\
|
||||
pixman_glyph_cache_lookup,'pixman_glyph_cache_lookup',\
|
||||
pixman_glyph_cache_remove,'pixman_glyph_cache_remove',\
|
||||
pixman_glyph_cache_thaw,'pixman_glyph_cache_thaw',\
|
||||
pixman_glyph_get_extents,'pixman_glyph_get_extents',\
|
||||
pixman_glyph_get_mask_format,'pixman_glyph_get_mask_format',\
|
||||
pixman_image_composite,'pixman_image_composite',\
|
||||
pixman_image_composite32,'pixman_image_composite32',\
|
||||
pixman_image_create_bits,'pixman_image_create_bits',\
|
||||
pixman_image_create_bits_no_clear,'pixman_image_create_bits_no_clear',\
|
||||
pixman_image_create_conical_gradient,'pixman_image_create_conical_gradient',\
|
||||
pixman_image_create_linear_gradient,'pixman_image_create_linear_gradient',\
|
||||
pixman_image_create_radial_gradient,'pixman_image_create_radial_gradient',\
|
||||
pixman_image_create_solid_fill,'pixman_image_create_solid_fill',\
|
||||
pixman_image_fill_boxes,'pixman_image_fill_boxes',\
|
||||
pixman_image_fill_rectangles,'pixman_image_fill_rectangles',\
|
||||
pixman_image_get_component_alpha,'pixman_image_get_component_alpha',\
|
||||
pixman_image_get_data,'pixman_image_get_data',\
|
||||
pixman_image_get_depth,'pixman_image_get_depth',\
|
||||
pixman_image_get_destroy_data,'pixman_image_get_destroy_data',\
|
||||
pixman_image_get_format,'pixman_image_get_format',\
|
||||
pixman_image_get_height,'pixman_image_get_height',\
|
||||
pixman_image_get_stride,'pixman_image_get_stride',\
|
||||
pixman_image_get_width,'pixman_image_get_width',\
|
||||
pixman_image_ref,'pixman_image_ref',\
|
||||
pixman_image_set_accessors,'pixman_image_set_accessors',\
|
||||
pixman_image_set_alpha_map,'pixman_image_set_alpha_map',\
|
||||
pixman_image_set_clip_region,'pixman_image_set_clip_region',\
|
||||
pixman_image_set_clip_region32,'pixman_image_set_clip_region32',\
|
||||
pixman_image_set_component_alpha,'pixman_image_set_component_alpha',\
|
||||
pixman_image_set_destroy_function,'pixman_image_set_destroy_function',\
|
||||
pixman_image_set_filter,'pixman_image_set_filter',\
|
||||
pixman_image_set_has_client_clip,'pixman_image_set_has_client_clip',\
|
||||
pixman_image_set_indexed,'pixman_image_set_indexed',\
|
||||
pixman_image_set_repeat,'pixman_image_set_repeat',\
|
||||
pixman_image_set_source_clipping,'pixman_image_set_source_clipping',\
|
||||
pixman_image_set_transform,'pixman_image_set_transform',\
|
||||
pixman_image_unref,'pixman_image_unref',\
|
||||
pixman_line_fixed_edge_init,'pixman_line_fixed_edge_init',\
|
||||
pixman_rasterize_edges,'pixman_rasterize_edges',\
|
||||
pixman_rasterize_trapezoid,'pixman_rasterize_trapezoid',\
|
||||
pixman_region32_clear,'pixman_region32_clear',\
|
||||
pixman_region32_contains_point,'pixman_region32_contains_point',\
|
||||
pixman_region32_contains_rectangle,'pixman_region32_contains_rectangle',\
|
||||
pixman_region32_copy,'pixman_region32_copy',\
|
||||
pixman_region32_equal,'pixman_region32_equal',\
|
||||
pixman_region32_extents,'pixman_region32_extents',\
|
||||
pixman_region32_fini,'pixman_region32_fini',\
|
||||
pixman_region32_init,'pixman_region32_init',\
|
||||
pixman_region32_init_from_image,'pixman_region32_init_from_image',\
|
||||
pixman_region32_init_rect,'pixman_region32_init_rect',\
|
||||
pixman_region32_init_rects,'pixman_region32_init_rects',\
|
||||
pixman_region32_init_with_extents,'pixman_region32_init_with_extents',\
|
||||
pixman_region32_intersect,'pixman_region32_intersect',\
|
||||
pixman_region32_intersect_rect,'pixman_region32_intersect_rect',\
|
||||
pixman_region32_inverse,'pixman_region32_inverse',\
|
||||
pixman_region32_n_rects,'pixman_region32_n_rects',\
|
||||
pixman_region32_not_empty,'pixman_region32_not_empty',\
|
||||
pixman_region32_rectangles,'pixman_region32_rectangles',\
|
||||
pixman_region32_reset,'pixman_region32_reset',\
|
||||
pixman_region32_selfcheck,'pixman_region32_selfcheck',\
|
||||
pixman_region32_subtract,'pixman_region32_subtract',\
|
||||
pixman_region32_translate,'pixman_region32_translate',\
|
||||
pixman_region32_union,'pixman_region32_union',\
|
||||
pixman_region32_union_rect,'pixman_region32_union_rect',\
|
||||
pixman_region_clear,'pixman_region_clear',\
|
||||
pixman_region_contains_point,'pixman_region_contains_point',\
|
||||
pixman_region_contains_rectangle,'pixman_region_contains_rectangle',\
|
||||
pixman_region_copy,'pixman_region_copy',\
|
||||
pixman_region_equal,'pixman_region_equal',\
|
||||
pixman_region_extents,'pixman_region_extents',\
|
||||
pixman_region_fini,'pixman_region_fini',\
|
||||
pixman_region_init,'pixman_region_init',\
|
||||
pixman_region_init_from_image,'pixman_region_init_from_image',\
|
||||
pixman_region_init_rect,'pixman_region_init_rect',\
|
||||
pixman_region_init_rects,'pixman_region_init_rects',\
|
||||
pixman_region_init_with_extents,'pixman_region_init_with_extents',\
|
||||
pixman_region_intersect,'pixman_region_intersect',\
|
||||
pixman_region_intersect_rect,'pixman_region_intersect_rect',\
|
||||
pixman_region_inverse,'pixman_region_inverse',\
|
||||
pixman_region_n_rects,'pixman_region_n_rects',\
|
||||
pixman_region_not_empty,'pixman_region_not_empty',\
|
||||
pixman_region_rectangles,'pixman_region_rectangles',\
|
||||
pixman_region_reset,'pixman_region_reset',\
|
||||
pixman_region_selfcheck,'pixman_region_selfcheck',\
|
||||
pixman_region_set_static_pointers,'pixman_region_set_static_pointers',\
|
||||
pixman_region_subtract,'pixman_region_subtract',\
|
||||
pixman_region_translate,'pixman_region_translate',\
|
||||
pixman_region_union,'pixman_region_union',\
|
||||
pixman_region_union_rect,'pixman_region_union_rect',\
|
||||
pixman_sample_ceil_y,'pixman_sample_ceil_y',\
|
||||
pixman_sample_floor_y,'pixman_sample_floor_y',\
|
||||
pixman_transform_bounds,'pixman_transform_bounds',\
|
||||
pixman_transform_from_pixman_f_transform,'pixman_transform_from_pixman_f_transform',\
|
||||
pixman_transform_init_identity,'pixman_transform_init_identity',\
|
||||
pixman_transform_init_rotate,'pixman_transform_init_rotate',\
|
||||
pixman_transform_init_scale,'pixman_transform_init_scale',\
|
||||
pixman_transform_init_translate,'pixman_transform_init_translate',\
|
||||
pixman_transform_invert,'pixman_transform_invert',\
|
||||
pixman_transform_is_identity,'pixman_transform_is_identity',\
|
||||
pixman_transform_is_int_translate,'pixman_transform_is_int_translate',\
|
||||
pixman_transform_is_inverse,'pixman_transform_is_inverse',\
|
||||
pixman_transform_is_scale,'pixman_transform_is_scale',\
|
||||
pixman_transform_multiply,'pixman_transform_multiply',\
|
||||
pixman_transform_point,'pixman_transform_point',\
|
||||
pixman_transform_point_31_16,'pixman_transform_point_31_16',\
|
||||
pixman_transform_point_31_16_3d,'pixman_transform_point_31_16_3d',\
|
||||
pixman_transform_point_31_16_affine,'pixman_transform_point_31_16_affine',\
|
||||
pixman_transform_point_3d,'pixman_transform_point_3d',\
|
||||
pixman_transform_rotate,'pixman_transform_rotate',\
|
||||
pixman_transform_scale,'pixman_transform_scale',\
|
||||
pixman_transform_translate,'pixman_transform_translate',\
|
||||
pixman_version,'pixman_version',\
|
||||
pixman_version_string,'pixman_version_string'
|
42
programs/develop/libraries/pixman/COPYING
Normal file
42
programs/develop/libraries/pixman/COPYING
Normal file
@ -0,0 +1,42 @@
|
||||
The following is the MIT license, agreed upon by most contributors.
|
||||
Copyright holders of new code should use this license statement where
|
||||
possible. They may also add themselves to the list below.
|
||||
|
||||
/*
|
||||
* Copyright 1987, 1988, 1989, 1998 The Open Group
|
||||
* Copyright 1987, 1988, 1989 Digital Equipment Corporation
|
||||
* Copyright 1999, 2004, 2008 Keith Packard
|
||||
* Copyright 2000 SuSE, Inc.
|
||||
* Copyright 2000 Keith Packard, member of The XFree86 Project, Inc.
|
||||
* Copyright 2004, 2005, 2007, 2008, 2009, 2010 Red Hat, Inc.
|
||||
* Copyright 2004 Nicholas Miell
|
||||
* Copyright 2005 Lars Knoll & Zack Rusin, Trolltech
|
||||
* Copyright 2005 Trolltech AS
|
||||
* Copyright 2007 Luca Barbato
|
||||
* Copyright 2008 Aaron Plattner, NVIDIA Corporation
|
||||
* Copyright 2008 Rodrigo Kumpera
|
||||
* Copyright 2008 André Tupinambá
|
||||
* Copyright 2008 Mozilla Corporation
|
||||
* Copyright 2008 Frederic Plourde
|
||||
* Copyright 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2009, 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.
|
||||
*/
|
@ -2,45 +2,52 @@
|
||||
LIBRARY = pixman-1
|
||||
|
||||
CC = gcc
|
||||
CFLAGS = -U_Win32 -U_WIN32 -U__MINGW32__ -c -O2 -Wall -Winline -fomit-frame-pointer
|
||||
|
||||
CFLAGS = -c -O2 -mmmx -Winline -fomit-frame-pointer
|
||||
LD = ld
|
||||
LDFLAGS = -shared -s -nostdlib -T ../newlib/dll.lds --entry _DllStartup --image-base=0 --out-implib $(LIBRARY).dll.a
|
||||
|
||||
LDIMPORT:= -nostdlib --out-implib libpiximp.a --exclude-libs libamz.a
|
||||
LDFLAGS:= -shared -s -T ../newlib/dll.lds --image-base 0
|
||||
STRIP = $(PREFIX)strip
|
||||
|
||||
DEFINES = -DHAVE_CONFIG_H -DPIXMAN_NO_TLS -DUSE_MMX
|
||||
|
||||
INCLUDES = -I../pixman -I../newlib/include
|
||||
INCLUDES= -I. -I../newlib/include
|
||||
|
||||
LIBPATH:= -L../newlib
|
||||
|
||||
LIBS:= -lamz -lgcc -lcimp
|
||||
LIBS:= -ldll -lc.dll -lgcc
|
||||
|
||||
DEFINES = -DHAVE_CONFIG_H
|
||||
|
||||
|
||||
SOURCES = \
|
||||
pixman-image.c \
|
||||
pixman.c \
|
||||
pixman-access.c \
|
||||
pixman-access-accessors.c \
|
||||
pixman-region16.c \
|
||||
pixman-region32.c \
|
||||
pixman-bits-image.c \
|
||||
pixman-combine32.c \
|
||||
pixman-combine64.c \
|
||||
pixman-utils.c \
|
||||
pixman-combine-float.c \
|
||||
pixman-conical-gradient.c \
|
||||
pixman-edge.c \
|
||||
pixman-edge-accessors.c \
|
||||
pixman-trap.c \
|
||||
pixman-timer.c \
|
||||
pixman-matrix.c \
|
||||
pixman-gradient-walker.c \
|
||||
pixman-linear-gradient.c \
|
||||
pixman-radial-gradient.c \
|
||||
pixman-bits-image.c \
|
||||
pixman.c \
|
||||
pixman-cpu.c \
|
||||
pixman-fast-path.c \
|
||||
pixman-implementation.c \
|
||||
pixman-solid-fill.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-noop.c \
|
||||
pixman-radial-gradient.c \
|
||||
pixman-region16.c \
|
||||
pixman-region32.c \
|
||||
pixman-solid-fill.c \
|
||||
pixman-timer.c \
|
||||
pixman-trap.c \
|
||||
pixman-utils.c \
|
||||
pixman-x86.c \
|
||||
pixman-mmx.c \
|
||||
pixman-sse2.c \
|
||||
$(NULL)
|
||||
|
||||
OBJECTS = $(patsubst %.c, %.o, $(SOURCES))
|
||||
@ -53,13 +60,21 @@ all:$(LIBRARY).a $(LIBRARY).dll
|
||||
$(LIBRARY).a: $(OBJECTS) Makefile
|
||||
ar cvrs $(LIBRARY).a $(OBJECTS)
|
||||
|
||||
$(LIBRARY).dll: $(OBJECTS) Makefile
|
||||
ld $(LDFLAGS) $(LDIMPORT) $(LIBPATH) -o $@ $(OBJECTS) $(LIBS)
|
||||
$(LIBRARY).dll: $(LIBRARY).def $(OBJECTS) Makefile
|
||||
$(LD) $(LDFLAGS) $(LIBPATH) -o $@ $(LIBRARY).def $(OBJECTS) $(LIBS)
|
||||
$(STRIP) $@
|
||||
sed -f ../newlib/cmd1.sed $(LIBRARY).def > mem
|
||||
sed -f ../newlib/cmd2.sed mem >$(LIBRARY).inc
|
||||
|
||||
|
||||
%.o: %.c $(SOURCES) Makefile
|
||||
%.o : %.c Makefile
|
||||
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o $@ $<
|
||||
|
||||
pixman-mmx.o: pixman-mmx.c Makefile
|
||||
$(CC) $(CFLAGS) -mmmx $(DEFINES) $(INCLUDES) -o $@ $<
|
||||
|
||||
pixman-sse2.o: pixman-sse2.c Makefile
|
||||
$(CC) $(CFLAGS) -msse2 $(DEFINES) $(INCLUDES) -o $@ $<
|
||||
|
||||
|
||||
clean:
|
||||
-rm -f *.o
|
||||
|
@ -1,22 +1,116 @@
|
||||
pixman is a library that provides low-level pixel manipulation
|
||||
Pixman is a library that provides low-level pixel manipulation
|
||||
features such as image compositing and trapezoid rasterization.
|
||||
|
||||
All questions regarding this software should be directed to the pixman
|
||||
Questions, bug reports and patches should be directed to the pixman
|
||||
mailing list:
|
||||
|
||||
http://lists.freedesktop.org/mailman/listinfo/pixman
|
||||
|
||||
Please send patches and bug reports either to the mailing list above,
|
||||
or file them at the freedesktop bug tracker:
|
||||
You can also file bugs at
|
||||
|
||||
https://bugs.freedesktop.org/enter_bug.cgi?product=pixman
|
||||
|
||||
The master development code repository can be found at:
|
||||
For real time discussions about pixman, feel free to join the IRC
|
||||
channels #cairo and #xorg-devel on the FreeNode IRC network.
|
||||
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
In order to contribute to pixman, you will need a working knowledge of
|
||||
the git version control system. For a quick getting started guide,
|
||||
there is the "Everyday Git With 20 Commands Or So guide"
|
||||
|
||||
http://www.kernel.org/pub/software/scm/git/docs/everyday.html
|
||||
|
||||
from the Git homepage. For more in depth git documentation, see the
|
||||
resources on the Git community documentation page:
|
||||
|
||||
http://git-scm.com/documentation
|
||||
|
||||
Pixman uses the infrastructure from the freedesktop.org umbrella
|
||||
project. For instructions about how to use the git service on
|
||||
freedesktop.org, see:
|
||||
|
||||
http://www.freedesktop.org/wiki/Infrastructure/git/Developers
|
||||
|
||||
The Pixman master repository can be found at:
|
||||
|
||||
git://anongit.freedesktop.org/git/pixman
|
||||
|
||||
http://gitweb.freedesktop.org/?p=pixman;a=summary
|
||||
and browsed on the web here:
|
||||
|
||||
For more information on the git code manager, see:
|
||||
http://cgit.freedesktop.org/pixman/
|
||||
|
||||
http://wiki.x.org/wiki/GitPage
|
||||
|
||||
Sending patches
|
||||
---------------
|
||||
|
||||
The general workflow for sending patches is to first make sure that
|
||||
git can send mail on your system. Then,
|
||||
|
||||
- create a branch off of master in your local git repository
|
||||
|
||||
- make your changes as one or more commits
|
||||
|
||||
- use the
|
||||
|
||||
git send-email
|
||||
|
||||
command to send the patch series to pixman@lists.freedesktop.org.
|
||||
|
||||
In order for your patches to be accepted, please consider the
|
||||
following guidelines:
|
||||
|
||||
- This link:
|
||||
|
||||
http://www.kernel.org/pub/software/scm/git/docs/user-manual.html#patch-series
|
||||
|
||||
describes how what a good patch series is, and to create one with
|
||||
git.
|
||||
|
||||
- At each point in the series, pixman should compile and the test
|
||||
suite should pass.
|
||||
|
||||
The exception here is if you are changing the test suite to
|
||||
demonstrate a bug. In this case, make one commit that makes the
|
||||
test suite fail due to the bug, and then another commit that fixes
|
||||
the bug.
|
||||
|
||||
You can run the test suite with
|
||||
|
||||
make check
|
||||
|
||||
It will take around two minutes to run on a modern PC.
|
||||
|
||||
- Follow the coding style described in the CODING_STYLE file
|
||||
|
||||
- For bug fixes, include an update to the test suite to make sure
|
||||
the bug doesn't reappear.
|
||||
|
||||
- For new features, add tests of the feature to the test
|
||||
suite. Also, add a program demonstrating the new feature to the
|
||||
demos/ directory.
|
||||
|
||||
- Write descriptive commit messages. Useful information to include:
|
||||
- Benchmark results, before and after
|
||||
- Description of the bug that was fixed
|
||||
- Detailed rationale for any new API
|
||||
- Alternative approaches that were rejected (and why they
|
||||
don't work)
|
||||
- If review comments were incorporated, a brief version
|
||||
history describing what those changes were.
|
||||
|
||||
- For big patch series, send an introductory email with an overall
|
||||
description of the patch series, including benchmarks and
|
||||
motivation. Each commit message should still be descriptive and
|
||||
include enough information to understand why this particular commit
|
||||
was necessary.
|
||||
|
||||
Pixman has high standards for code quality and so almost everybody
|
||||
should expect to have the first versions of their patches rejected.
|
||||
|
||||
If you think that the reviewers are wrong about something, or that the
|
||||
guidelines above are wrong, feel free to discuss the issue on the
|
||||
list. The purpose of the guidelines and code review is to ensure high
|
||||
code quality; it is not an exercise in compliance.
|
||||
|
@ -10,6 +10,15 @@
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
/* #undef HAVE_DLFCN_H */
|
||||
|
||||
/* Whether we have feenableexcept() */
|
||||
/* #undef HAVE_FEENABLEEXCEPT */
|
||||
|
||||
/* Define to 1 if we have <fenv.h> */
|
||||
#define HAVE_FENV_H 1
|
||||
|
||||
/* Whether the tool chain supports __float128 */
|
||||
#define HAVE_FLOAT128 /**/
|
||||
|
||||
/* Define to 1 if you have the `getisax' function. */
|
||||
/* #undef HAVE_GETISAX */
|
||||
|
||||
@ -25,9 +34,15 @@
|
||||
/* Define to 1 if you have the `pixman-1' library (-lpixman-1). */
|
||||
/* #undef HAVE_LIBPIXMAN_1 */
|
||||
|
||||
/* Whether we have libpng */
|
||||
/* #undef HAVE_LIBPNG */
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Whether we have mmap() */
|
||||
#define HAVE_MMAP
|
||||
|
||||
/* Whether we have mprotect() */
|
||||
#define HAVE_MPROTECT 1
|
||||
|
||||
@ -72,13 +87,13 @@
|
||||
#define PACKAGE "pixman"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT ""pixman@lists.freedesktop.org""
|
||||
#define PACKAGE_BUGREPORT "pixman@lists.freedesktop.org"
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "pixman"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "pixman 0.20.2"
|
||||
#define PACKAGE_STRING "pixman 0.30.2"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "pixman"
|
||||
@ -87,7 +102,7 @@
|
||||
#define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "0.20.2"
|
||||
#define PACKAGE_VERSION "0.30.2"
|
||||
|
||||
/* enable TIMER_BEGIN/TIMER_END macros */
|
||||
/* #undef PIXMAN_TIMERS */
|
||||
@ -98,8 +113,14 @@
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Whether the tool chain supports __thread */
|
||||
//#define TOOLCHAIN_SUPPORTS__THREAD /**/
|
||||
/* The compiler supported TLS storage class */
|
||||
#define TLS __thread
|
||||
|
||||
/* Whether the tool chain supports __attribute__((constructor)) */
|
||||
#define TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR /**/
|
||||
|
||||
/* use ARM IWMMXT compiler intrinsics */
|
||||
/* #undef USE_ARM_IWMMXT */
|
||||
|
||||
/* use ARM NEON assembly optimizations */
|
||||
/* #undef USE_ARM_NEON */
|
||||
@ -110,20 +131,26 @@
|
||||
/* use GNU-style inline assembler */
|
||||
#define USE_GCC_INLINE_ASM 1
|
||||
|
||||
/* use MMX compiler intrinsics */
|
||||
#define USE_MMX 1
|
||||
/* use Loongson Multimedia Instructions */
|
||||
/* #undef USE_LOONGSON_MMI */
|
||||
|
||||
/* use MIPS DSPr2 assembly optimizations */
|
||||
/* #undef USE_MIPS_DSPR2 */
|
||||
|
||||
/* use OpenMP in the test suite */
|
||||
//#define USE_OPENMP 1
|
||||
/* #undef USE_OPENMP */
|
||||
|
||||
/* use SSE2 compiler intrinsics */
|
||||
//#define USE_SSE2 1
|
||||
#define USE_SSE2 1
|
||||
|
||||
/* use VMX compiler intrinsics */
|
||||
/* #undef USE_VMX */
|
||||
|
||||
/* use x86 MMX compiler intrinsics */
|
||||
#define USE_X86_MMX 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "0.20.2"
|
||||
#define VERSION "0.30.2"
|
||||
|
||||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||
significant byte first (like Motorola and SPARC, unlike Intel). */
|
||||
@ -142,3 +169,6 @@
|
||||
#ifndef __cplusplus
|
||||
/* #undef inline */
|
||||
#endif
|
||||
|
||||
/* Define to sqrt if you do not have the `sqrtf' function. */
|
||||
/* #undef sqrtf */
|
||||
|
148
programs/develop/libraries/pixman/pixman-1.def
Normal file
148
programs/develop/libraries/pixman/pixman-1.def
Normal file
@ -0,0 +1,148 @@
|
||||
EXPORTS
|
||||
_pixman_internal_only_get_implementation
|
||||
pixman_add_trapezoids
|
||||
pixman_add_traps
|
||||
pixman_add_triangles
|
||||
pixman_blt
|
||||
pixman_composite_glyphs
|
||||
pixman_composite_glyphs_no_mask
|
||||
pixman_composite_trapezoids
|
||||
pixman_composite_triangles
|
||||
pixman_compute_composite_region
|
||||
pixman_disable_out_of_bounds_workaround
|
||||
pixman_edge_init
|
||||
pixman_edge_step
|
||||
pixman_f_transform_bounds
|
||||
pixman_f_transform_from_pixman_transform
|
||||
pixman_f_transform_init_identity
|
||||
pixman_f_transform_init_rotate
|
||||
pixman_f_transform_init_scale
|
||||
pixman_f_transform_init_translate
|
||||
pixman_f_transform_invert
|
||||
pixman_f_transform_multiply
|
||||
pixman_f_transform_point
|
||||
pixman_f_transform_point_3d
|
||||
pixman_f_transform_rotate
|
||||
pixman_f_transform_scale
|
||||
pixman_f_transform_translate
|
||||
pixman_fill
|
||||
pixman_filter_create_separable_convolution
|
||||
pixman_format_supported_destination
|
||||
pixman_format_supported_source
|
||||
pixman_glyph_cache_create
|
||||
pixman_glyph_cache_destroy
|
||||
pixman_glyph_cache_freeze
|
||||
pixman_glyph_cache_insert
|
||||
pixman_glyph_cache_lookup
|
||||
pixman_glyph_cache_remove
|
||||
pixman_glyph_cache_thaw
|
||||
pixman_glyph_get_extents
|
||||
pixman_glyph_get_mask_format
|
||||
pixman_image_composite
|
||||
pixman_image_composite32
|
||||
pixman_image_create_bits
|
||||
pixman_image_create_bits_no_clear
|
||||
pixman_image_create_conical_gradient
|
||||
pixman_image_create_linear_gradient
|
||||
pixman_image_create_radial_gradient
|
||||
pixman_image_create_solid_fill
|
||||
pixman_image_fill_boxes
|
||||
pixman_image_fill_rectangles
|
||||
pixman_image_get_component_alpha
|
||||
pixman_image_get_data
|
||||
pixman_image_get_depth
|
||||
pixman_image_get_destroy_data
|
||||
pixman_image_get_format
|
||||
pixman_image_get_height
|
||||
pixman_image_get_stride
|
||||
pixman_image_get_width
|
||||
pixman_image_ref
|
||||
pixman_image_set_accessors
|
||||
pixman_image_set_alpha_map
|
||||
pixman_image_set_clip_region
|
||||
pixman_image_set_clip_region32
|
||||
pixman_image_set_component_alpha
|
||||
pixman_image_set_destroy_function
|
||||
pixman_image_set_filter
|
||||
pixman_image_set_has_client_clip
|
||||
pixman_image_set_indexed
|
||||
pixman_image_set_repeat
|
||||
pixman_image_set_source_clipping
|
||||
pixman_image_set_transform
|
||||
pixman_image_unref
|
||||
pixman_line_fixed_edge_init
|
||||
pixman_rasterize_edges
|
||||
pixman_rasterize_trapezoid
|
||||
pixman_region32_clear
|
||||
pixman_region32_contains_point
|
||||
pixman_region32_contains_rectangle
|
||||
pixman_region32_copy
|
||||
pixman_region32_equal
|
||||
pixman_region32_extents
|
||||
pixman_region32_fini
|
||||
pixman_region32_init
|
||||
pixman_region32_init_from_image
|
||||
pixman_region32_init_rect
|
||||
pixman_region32_init_rects
|
||||
pixman_region32_init_with_extents
|
||||
pixman_region32_intersect
|
||||
pixman_region32_intersect_rect
|
||||
pixman_region32_inverse
|
||||
pixman_region32_n_rects
|
||||
pixman_region32_not_empty
|
||||
pixman_region32_rectangles
|
||||
pixman_region32_reset
|
||||
pixman_region32_selfcheck
|
||||
pixman_region32_subtract
|
||||
pixman_region32_translate
|
||||
pixman_region32_union
|
||||
pixman_region32_union_rect
|
||||
pixman_region_clear
|
||||
pixman_region_contains_point
|
||||
pixman_region_contains_rectangle
|
||||
pixman_region_copy
|
||||
pixman_region_equal
|
||||
pixman_region_extents
|
||||
pixman_region_fini
|
||||
pixman_region_init
|
||||
pixman_region_init_from_image
|
||||
pixman_region_init_rect
|
||||
pixman_region_init_rects
|
||||
pixman_region_init_with_extents
|
||||
pixman_region_intersect
|
||||
pixman_region_intersect_rect
|
||||
pixman_region_inverse
|
||||
pixman_region_n_rects
|
||||
pixman_region_not_empty
|
||||
pixman_region_rectangles
|
||||
pixman_region_reset
|
||||
pixman_region_selfcheck
|
||||
pixman_region_set_static_pointers
|
||||
pixman_region_subtract
|
||||
pixman_region_translate
|
||||
pixman_region_union
|
||||
pixman_region_union_rect
|
||||
pixman_sample_ceil_y
|
||||
pixman_sample_floor_y
|
||||
pixman_transform_bounds
|
||||
pixman_transform_from_pixman_f_transform
|
||||
pixman_transform_init_identity
|
||||
pixman_transform_init_rotate
|
||||
pixman_transform_init_scale
|
||||
pixman_transform_init_translate
|
||||
pixman_transform_invert
|
||||
pixman_transform_is_identity
|
||||
pixman_transform_is_int_translate
|
||||
pixman_transform_is_inverse
|
||||
pixman_transform_is_scale
|
||||
pixman_transform_multiply
|
||||
pixman_transform_point
|
||||
pixman_transform_point_31_16
|
||||
pixman_transform_point_31_16_3d
|
||||
pixman_transform_point_31_16_affine
|
||||
pixman_transform_point_3d
|
||||
pixman_transform_rotate
|
||||
pixman_transform_scale
|
||||
pixman_transform_translate
|
||||
pixman_version
|
||||
pixman_version_string
|
File diff suppressed because it is too large
Load Diff
@ -1,21 +1,10 @@
|
||||
#ifdef PIXMAN_FB_ACCESSORS
|
||||
|
||||
#define ACCESS(sym) sym##_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 MEMCPY_WRAPPED(img, dst, src, size) \
|
||||
do { \
|
||||
size_t _i; \
|
||||
uint8_t *_dst = (uint8_t*)(dst), *_src = (uint8_t*)(src); \
|
||||
for(_i = 0; _i < size; _i++) { \
|
||||
WRITE((img), _dst +_i, READ((img), _src + _i)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define MEMSET_WRAPPED(img, dst, val, size) \
|
||||
do { \
|
||||
size_t _i; \
|
||||
@ -27,12 +16,8 @@
|
||||
|
||||
#else
|
||||
|
||||
#define ACCESS(sym) sym
|
||||
|
||||
#define READ(img, ptr) (*(ptr))
|
||||
#define WRITE(img, ptr, val) (*(ptr) = (val))
|
||||
#define MEMCPY_WRAPPED(img, dst, src, size) \
|
||||
memcpy(dst, src, size)
|
||||
#define MEMSET_WRAPPED(img, dst, val, size) \
|
||||
memset(dst, val, size)
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
1016
programs/develop/libraries/pixman/pixman-combine-float.c
Normal file
1016
programs/develop/libraries/pixman/pixman-combine-float.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,26 @@
|
||||
/* 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"
|
||||
/*
|
||||
* 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
|
||||
@ -10,10 +29,9 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "pixman-private.h"
|
||||
|
||||
#include "pixman-combine32.h"
|
||||
|
||||
/*** per channel helper functions ***/
|
||||
/* component alpha helper functions */
|
||||
|
||||
static void
|
||||
combine_mask_ca (uint32_t *src, uint32_t *mask)
|
||||
@ -95,15 +113,11 @@ combine_mask_alpha_ca (const uint32_t *src, uint32_t *mask)
|
||||
/*
|
||||
* There are two ways of handling alpha -- either as a single unified value or
|
||||
* a separate value for each component, hence each macro must have two
|
||||
* versions. The unified alpha version has a 'U' at the end of the name,
|
||||
* the component version has a 'C'. Similarly, functions which deal with
|
||||
* versions. The unified alpha version has a 'u' at the end of the name,
|
||||
* the component version has a 'ca'. Similarly, functions which deal with
|
||||
* this difference will have two versions using the same convention.
|
||||
*/
|
||||
|
||||
/*
|
||||
* All of the composing functions
|
||||
*/
|
||||
|
||||
static force_inline uint32_t
|
||||
combine_mask (const uint32_t *src, const uint32_t *mask, int i)
|
||||
{
|
||||
@ -158,7 +172,9 @@ combine_src_u (pixman_implementation_t *imp,
|
||||
int i;
|
||||
|
||||
if (!mask)
|
||||
{
|
||||
memcpy (dest, src, width * sizeof (uint32_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < width; ++i)
|
||||
@ -170,7 +186,6 @@ combine_src_u (pixman_implementation_t *imp,
|
||||
}
|
||||
}
|
||||
|
||||
/* if the Src is opaque, call combine_src_u */
|
||||
static void
|
||||
combine_over_u (pixman_implementation_t *imp,
|
||||
pixman_op_t op,
|
||||
@ -181,18 +196,61 @@ combine_over_u (pixman_implementation_t *imp,
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < width; ++i)
|
||||
if (!mask)
|
||||
{
|
||||
uint32_t s = combine_mask (src, mask, i);
|
||||
uint32_t d = *(dest + i);
|
||||
uint32_t ia = ALPHA_8 (~s);
|
||||
|
||||
UN8x4_MUL_UN8_ADD_UN8x4 (d, ia, s);
|
||||
*(dest + i) = d;
|
||||
for (i = 0; i < width; ++i)
|
||||
{
|
||||
uint32_t s = *(src + i);
|
||||
uint32_t a = ALPHA_8 (s);
|
||||
if (a == 0xFF)
|
||||
{
|
||||
*(dest + i) = s;
|
||||
}
|
||||
else if (s)
|
||||
{
|
||||
uint32_t d = *(dest + i);
|
||||
uint32_t ia = a ^ 0xFF;
|
||||
UN8x4_MUL_UN8_ADD_UN8x4 (d, ia, s);
|
||||
*(dest + i) = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < width; ++i)
|
||||
{
|
||||
uint32_t m = ALPHA_8 (*(mask + i));
|
||||
if (m == 0xFF)
|
||||
{
|
||||
uint32_t s = *(src + i);
|
||||
uint32_t a = ALPHA_8 (s);
|
||||
if (a == 0xFF)
|
||||
{
|
||||
*(dest + i) = s;
|
||||
}
|
||||
else if (s)
|
||||
{
|
||||
uint32_t d = *(dest + i);
|
||||
uint32_t ia = a ^ 0xFF;
|
||||
UN8x4_MUL_UN8_ADD_UN8x4 (d, ia, s);
|
||||
*(dest + i) = d;
|
||||
}
|
||||
}
|
||||
else if (m)
|
||||
{
|
||||
uint32_t s = *(src + i);
|
||||
if (s)
|
||||
{
|
||||
uint32_t d = *(dest + i);
|
||||
UN8x4_MUL_UN8 (s, m);
|
||||
UN8x4_MUL_UN8_ADD_UN8x4 (d, ALPHA_8 (~s), s);
|
||||
*(dest + i) = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if the Dst is opaque, this is a noop */
|
||||
static void
|
||||
combine_over_reverse_u (pixman_implementation_t *imp,
|
||||
pixman_op_t op,
|
||||
@ -213,7 +271,6 @@ combine_over_reverse_u (pixman_implementation_t *imp,
|
||||
}
|
||||
}
|
||||
|
||||
/* if the Dst is opaque, call combine_src_u */
|
||||
static void
|
||||
combine_in_u (pixman_implementation_t *imp,
|
||||
pixman_op_t op,
|
||||
@ -233,7 +290,6 @@ combine_in_u (pixman_implementation_t *imp,
|
||||
}
|
||||
}
|
||||
|
||||
/* if the Src is opaque, this is a noop */
|
||||
static void
|
||||
combine_in_reverse_u (pixman_implementation_t *imp,
|
||||
pixman_op_t op,
|
||||
@ -254,7 +310,6 @@ combine_in_reverse_u (pixman_implementation_t *imp,
|
||||
}
|
||||
}
|
||||
|
||||
/* if the Dst is opaque, call combine_clear */
|
||||
static void
|
||||
combine_out_u (pixman_implementation_t *imp,
|
||||
pixman_op_t op,
|
||||
@ -274,7 +329,6 @@ combine_out_u (pixman_implementation_t *imp,
|
||||
}
|
||||
}
|
||||
|
||||
/* if the Src is opaque, call combine_clear */
|
||||
static void
|
||||
combine_out_reverse_u (pixman_implementation_t *imp,
|
||||
pixman_op_t op,
|
||||
@ -295,9 +349,6 @@ combine_out_reverse_u (pixman_implementation_t *imp,
|
||||
}
|
||||
}
|
||||
|
||||
/* if the Src is opaque, call combine_in_u */
|
||||
/* if the Dst is opaque, call combine_over_u */
|
||||
/* if both the Src and Dst are opaque, call combine_src_u */
|
||||
static void
|
||||
combine_atop_u (pixman_implementation_t *imp,
|
||||
pixman_op_t op,
|
||||
@ -320,9 +371,6 @@ combine_atop_u (pixman_implementation_t *imp,
|
||||
}
|
||||
}
|
||||
|
||||
/* if the Src is opaque, call combine_over_reverse_u */
|
||||
/* if the Dst is opaque, call combine_in_reverse_u */
|
||||
/* if both the Src and Dst are opaque, call combine_dst_u */
|
||||
static void
|
||||
combine_atop_reverse_u (pixman_implementation_t *imp,
|
||||
pixman_op_t op,
|
||||
@ -345,9 +393,6 @@ combine_atop_reverse_u (pixman_implementation_t *imp,
|
||||
}
|
||||
}
|
||||
|
||||
/* if the Src is opaque, call combine_over_u */
|
||||
/* if the Dst is opaque, call combine_over_reverse_u */
|
||||
/* if both the Src and Dst are opaque, call combine_clear */
|
||||
static void
|
||||
combine_xor_u (pixman_implementation_t *imp,
|
||||
pixman_op_t op,
|
||||
@ -389,9 +434,6 @@ combine_add_u (pixman_implementation_t *imp,
|
||||
}
|
||||
}
|
||||
|
||||
/* if the Src is opaque, call combine_add_u */
|
||||
/* if the Dst is opaque, call combine_add_u */
|
||||
/* if both the Src and Dst are opaque, call combine_add_u */
|
||||
static void
|
||||
combine_saturate_u (pixman_implementation_t *imp,
|
||||
pixman_op_t op,
|
||||
@ -441,14 +483,13 @@ combine_saturate_u (pixman_implementation_t *imp,
|
||||
* PDF_NON_SEPARABLE_BLEND_MODE macros, which take the blend function as an
|
||||
* argument. Note that this implementation operates on premultiplied colors,
|
||||
* while the PDF specification does not. Therefore the code uses the formula
|
||||
* ar.Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as)
|
||||
* Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Multiply
|
||||
* B(Dca, ad, Sca, as) = Dca.Sca
|
||||
*/
|
||||
|
||||
static void
|
||||
combine_multiply_u (pixman_implementation_t *imp,
|
||||
pixman_op_t op,
|
||||
@ -493,7 +534,7 @@ combine_multiply_ca (pixman_implementation_t *imp,
|
||||
uint32_t r = d;
|
||||
uint32_t dest_ia = ALPHA_8 (~d);
|
||||
|
||||
combine_mask_value_ca (&s, &m);
|
||||
combine_mask_ca (&s, &m);
|
||||
|
||||
UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (r, ~m, s, dest_ia);
|
||||
UN8x4_MUL_UN8x4 (d, s);
|
||||
@ -526,7 +567,7 @@ combine_multiply_ca (pixman_implementation_t *imp,
|
||||
UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (result, isa, s, ida); \
|
||||
\
|
||||
*(dest + i) = result + \
|
||||
(DIV_ONE_UN8 (sa * da) << A_SHIFT) + \
|
||||
(DIV_ONE_UN8 (sa * (uint32_t)da) << A_SHIFT) + \
|
||||
(blend_ ## name (RED_8 (d), da, RED_8 (s), sa) << R_SHIFT) + \
|
||||
(blend_ ## name (GREEN_8 (d), da, GREEN_8 (s), sa) << G_SHIFT) + \
|
||||
(blend_ ## name (BLUE_8 (d), da, BLUE_8 (s), sa)); \
|
||||
@ -550,13 +591,13 @@ combine_multiply_ca (pixman_implementation_t *imp,
|
||||
uint8_t ida = ~da; \
|
||||
uint32_t result; \
|
||||
\
|
||||
combine_mask_value_ca (&s, &m); \
|
||||
combine_mask_ca (&s, &m); \
|
||||
\
|
||||
result = d; \
|
||||
UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (result, ~m, s, ida); \
|
||||
\
|
||||
result += \
|
||||
(DIV_ONE_UN8 (ALPHA_8 (m) * da) << A_SHIFT) + \
|
||||
(DIV_ONE_UN8 (ALPHA_8 (m) * (uint32_t)da) << A_SHIFT) + \
|
||||
(blend_ ## name (RED_8 (d), da, RED_8 (s), RED_8 (m)) << R_SHIFT) + \
|
||||
(blend_ ## name (GREEN_8 (d), da, GREEN_8 (s), GREEN_8 (m)) << G_SHIFT) + \
|
||||
(blend_ ## name (BLUE_8 (d), da, BLUE_8 (s), BLUE_8 (m))); \
|
||||
@ -853,7 +894,7 @@ PDF_SEPARABLE_BLEND_MODE (exclusion)
|
||||
*
|
||||
* r * set_sat (C, s) = set_sat (x * C, r * s)
|
||||
*
|
||||
* The above holds for all non-zero x, because they x'es in the fraction for
|
||||
* The above holds for all non-zero x, because the x'es in the fraction for
|
||||
* C_mid cancel out. Specifically, it holds for x = r:
|
||||
*
|
||||
* r * set_sat (C, s) = set_sat (r_c, rs)
|
||||
@ -889,8 +930,7 @@ PDF_SEPARABLE_BLEND_MODE (exclusion)
|
||||
*
|
||||
* a_s * a_d * B(s, d)
|
||||
* = a_s * a_d * set_lum (set_sat (S/a_s, SAT (D/a_d)), LUM (D/a_d), 1)
|
||||
* = a_s * a_d * set_lum (set_sat (a_d * S, a_s * SAT (D)),
|
||||
* a_s * LUM (D), a_s * a_d)
|
||||
* = set_lum (set_sat (a_d * S, a_s * SAT (D)), a_s * LUM (D), a_s * a_d)
|
||||
*
|
||||
*/
|
||||
|
||||
@ -931,7 +971,7 @@ PDF_SEPARABLE_BLEND_MODE (exclusion)
|
||||
blend_ ## name (c, dc, da, sc, sa); \
|
||||
\
|
||||
*(dest + i) = result + \
|
||||
(DIV_ONE_UN8 (sa * da) << A_SHIFT) + \
|
||||
(DIV_ONE_UN8 (sa * (uint32_t)da) << A_SHIFT) + \
|
||||
(DIV_ONE_UN8 (c[0]) << R_SHIFT) + \
|
||||
(DIV_ONE_UN8 (c[1]) << G_SHIFT) + \
|
||||
(DIV_ONE_UN8 (c[2])); \
|
||||
@ -1148,9 +1188,7 @@ PDF_NON_SEPARABLE_BLEND_MODE (hsl_luminosity)
|
||||
#undef CH_MIN
|
||||
#undef PDF_NON_SEPARABLE_BLEND_MODE
|
||||
|
||||
/* Overlay
|
||||
*
|
||||
* All of the disjoint composing functions
|
||||
/* All of the disjoint/conjoint composing functions
|
||||
*
|
||||
* The four entries in the first column indicate what source contributions
|
||||
* come from each of the four areas of the picture -- areas covered by neither
|
||||
@ -1171,6 +1209,9 @@ PDF_NON_SEPARABLE_BLEND_MODE (hsl_luminosity)
|
||||
* (0,0,B,A) max(1-(1-b)/a,0) min(1,(1-a)/b) min(1,b/a) max(1-a/b,0)
|
||||
* (0,A,0,B) min(1,(1-b)/a) max(1-(1-a)/b,0) max(1-b/a,0) min(1,a/b)
|
||||
* (0,A,B,0) min(1,(1-b)/a) min(1,(1-a)/b) max(1-b/a,0) max(1-a/b,0)
|
||||
*
|
||||
* See http://marc.info/?l=xfree-render&m=99792000027857&w=2 for more
|
||||
* information about these operators.
|
||||
*/
|
||||
|
||||
#define COMBINE_A_OUT 1
|
||||
@ -1583,9 +1624,8 @@ combine_conjoint_xor_u (pixman_implementation_t *imp,
|
||||
combine_conjoint_general_u (dest, src, mask, width, COMBINE_XOR);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/*********************** Per Channel functions **************************/
|
||||
/************************************************************************/
|
||||
|
||||
/* Component alpha combiners */
|
||||
|
||||
static void
|
||||
combine_clear_ca (pixman_implementation_t *imp,
|
||||
@ -2462,4 +2502,3 @@ _pixman_setup_combiner_functions_32 (pixman_implementation_t *imp)
|
||||
imp->combine_32_ca[PIXMAN_OP_HSL_COLOR] = combine_dst;
|
||||
imp->combine_32_ca[PIXMAN_OP_HSL_LUMINOSITY] = combine_dst;
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,3 @@
|
||||
/* 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 8
|
||||
#define MASK 0xff
|
||||
#define ONE_HALF 0x80
|
||||
@ -24,19 +19,62 @@
|
||||
#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) * (b) + ONE_HALF, ((((t) >> G_SHIFT ) + (t) ) >> G_SHIFT ))
|
||||
((t) = (a) * (uint16_t)(b) + ONE_HALF, ((((t) >> G_SHIFT ) + (t) ) >> G_SHIFT ))
|
||||
|
||||
#define DIV_UN8(a, b) \
|
||||
(((uint16_t) (a) * MASK) / (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)
|
||||
@ -61,6 +99,7 @@
|
||||
/*
|
||||
* x_rb = min (x_rb + y_rb, 255)
|
||||
*/
|
||||
#ifndef UN8_rb_ADD_UN8_rb
|
||||
#define UN8_rb_ADD_UN8_rb(x, y, t) \
|
||||
do \
|
||||
{ \
|
||||
@ -68,6 +107,7 @@
|
||||
t |= RB_MASK_PLUS_ONE - ((t >> G_SHIFT) & RB_MASK); \
|
||||
x = (t & RB_MASK); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* x_rb = (x_rb * a_rb) / 255
|
||||
@ -213,6 +253,7 @@
|
||||
/*
|
||||
x_c = min(x_c + y_c, 255)
|
||||
*/
|
||||
#ifndef UN8x4_ADD_UN8x4
|
||||
#define UN8x4_ADD_UN8x4(x, y) \
|
||||
do \
|
||||
{ \
|
||||
@ -228,3 +269,4 @@
|
||||
\
|
||||
x = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,230 +0,0 @@
|
||||
/* 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) * (b) + ONE_HALF, ((((t) >> G_SHIFT ) + (t) ) >> G_SHIFT ))
|
||||
|
||||
#define DIV_UN16(a, b) \
|
||||
(((uint32_t) (a) * MASK) / (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)
|
@ -18,6 +18,18 @@
|
||||
# define FUNC ((const char*) ("???"))
|
||||
#endif
|
||||
|
||||
#if defined (__GNUC__)
|
||||
# define unlikely(expr) __builtin_expect ((expr), 0)
|
||||
#else
|
||||
# define unlikely(expr) (expr)
|
||||
#endif
|
||||
|
||||
#if defined (__GNUC__)
|
||||
# define MAYBE_UNUSED __attribute__((unused))
|
||||
#else
|
||||
# define MAYBE_UNUSED
|
||||
#endif
|
||||
|
||||
#ifndef INT16_MIN
|
||||
# define INT16_MIN (-32767-1)
|
||||
#endif
|
||||
@ -42,6 +54,19 @@
|
||||
# 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
|
||||
@ -74,6 +99,10 @@
|
||||
# define PIXMAN_EXPORT
|
||||
#endif
|
||||
|
||||
/* member offsets */
|
||||
#define CONTAINER_OF(type, member, data) \
|
||||
((type *)(((uint8_t *)data) - offsetof (type, member)))
|
||||
|
||||
/* TLS */
|
||||
#if defined(PIXMAN_NO_TLS)
|
||||
|
||||
@ -82,10 +111,10 @@
|
||||
# define PIXMAN_GET_THREAD_LOCAL(name) \
|
||||
(&name)
|
||||
|
||||
#elif defined(TOOLCHAIN_SUPPORTS__THREAD)
|
||||
#elif defined(TLS)
|
||||
|
||||
# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \
|
||||
static __thread type name
|
||||
static TLS type name
|
||||
# define PIXMAN_GET_THREAD_LOCAL(name) \
|
||||
(&name)
|
||||
|
||||
@ -191,8 +220,7 @@
|
||||
value = tls_ ## name ## _alloc (); \
|
||||
} \
|
||||
return value; \
|
||||
} \
|
||||
extern int no_such_variable
|
||||
}
|
||||
|
||||
# define PIXMAN_GET_THREAD_LOCAL(name) \
|
||||
tls_ ## name ## _get ()
|
||||
|
@ -50,16 +50,16 @@ coordinates_to_parameter (double x, double y, double angle)
|
||||
*/
|
||||
}
|
||||
|
||||
static void
|
||||
conical_gradient_get_scanline_32 (pixman_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
uint32_t * buffer,
|
||||
const uint32_t *mask)
|
||||
static uint32_t *
|
||||
conical_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
source_image_t *source = (source_image_t *)image;
|
||||
gradient_t *gradient = (gradient_t *)source;
|
||||
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;
|
||||
@ -71,9 +71,9 @@ conical_gradient_get_scanline_32 (pixman_image_t *image,
|
||||
double ry = y + 0.5;
|
||||
double rz = 1.;
|
||||
|
||||
_pixman_gradient_walker_init (&walker, gradient, source->common.repeat);
|
||||
_pixman_gradient_walker_init (&walker, gradient, image->common.repeat);
|
||||
|
||||
if (source->common.transform)
|
||||
if (image->common.transform)
|
||||
{
|
||||
pixman_vector_t v;
|
||||
|
||||
@ -82,19 +82,19 @@ conical_gradient_get_scanline_32 (pixman_image_t *image,
|
||||
v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2;
|
||||
v.vector[2] = pixman_fixed_1;
|
||||
|
||||
if (!pixman_transform_point_3d (source->common.transform, &v))
|
||||
return;
|
||||
if (!pixman_transform_point_3d (image->common.transform, &v))
|
||||
return iter->buffer;
|
||||
|
||||
cx = source->common.transform->matrix[0][0] / 65536.;
|
||||
cy = source->common.transform->matrix[1][0] / 65536.;
|
||||
cz = source->common.transform->matrix[2][0] / 65536.;
|
||||
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 =
|
||||
source->common.transform->matrix[2][0] == 0 &&
|
||||
image->common.transform->matrix[2][0] == 0 &&
|
||||
v.vector[2] == pixman_fixed_1;
|
||||
}
|
||||
|
||||
@ -155,17 +155,33 @@ conical_gradient_get_scanline_32 (pixman_image_t *image,
|
||||
rz += cz;
|
||||
}
|
||||
}
|
||||
|
||||
iter->y++;
|
||||
return iter->buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
conical_gradient_property_changed (pixman_image_t *image)
|
||||
static uint32_t *
|
||||
conical_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
image->common.get_scanline_32 = conical_gradient_get_scanline_32;
|
||||
image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64;
|
||||
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 (pixman_point_fixed_t * center,
|
||||
pixman_image_create_conical_gradient (const pixman_point_fixed_t * center,
|
||||
pixman_fixed_t angle,
|
||||
const pixman_gradient_stop_t *stops,
|
||||
int n_stops)
|
||||
@ -191,8 +207,6 @@ pixman_image_create_conical_gradient (pixman_point_fixed_t * center,
|
||||
conical->center = *center;
|
||||
conical->angle = (pixman_fixed_to_double (angle) / 180.0) * M_PI;
|
||||
|
||||
image->common.property_changed = conical_gradient_property_changed;
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
@ -1,598 +0,0 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
#if defined(USE_ARM_SIMD) && defined(_MSC_VER)
|
||||
/* Needed for EXCEPTION_ILLEGAL_INSTRUCTION */
|
||||
#include <windows.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)
|
||||
|
||||
#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 */
|
||||
|
||||
#else /* linux ELF */
|
||||
|
||||
#include <stdlib.h>
|
||||
#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 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;
|
||||
|
||||
static void
|
||||
pixman_arm_read_auxv ()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
#if defined(USE_ARM_SIMD)
|
||||
pixman_bool_t
|
||||
pixman_have_arm_simd (void)
|
||||
{
|
||||
if (!arm_tests_initialized)
|
||||
pixman_arm_read_auxv ();
|
||||
|
||||
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 ();
|
||||
|
||||
return arm_has_neon;
|
||||
}
|
||||
|
||||
#endif /* USE_ARM_NEON */
|
||||
|
||||
#endif /* linux */
|
||||
|
||||
#endif /* USE_ARM_SIMD || USE_ARM_NEON */
|
||||
|
||||
#if defined(USE_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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#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_MMX
|
||||
#define pixman_have_mmx() TRUE
|
||||
#endif
|
||||
#ifdef USE_SSE2
|
||||
#define pixman_have_sse2() TRUE
|
||||
#endif
|
||||
#endif /* __amd64__ */
|
||||
#endif
|
||||
|
||||
pixman_implementation_t *
|
||||
_pixman_choose_implementation (void)
|
||||
{
|
||||
#ifdef USE_SSE2
|
||||
if (pixman_have_sse2 ())
|
||||
return _pixman_implementation_create_sse2 ();
|
||||
#endif
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx ())
|
||||
return _pixman_implementation_create_mmx ();
|
||||
#endif
|
||||
|
||||
#ifdef USE_ARM_NEON
|
||||
if (pixman_have_arm_neon ())
|
||||
return _pixman_implementation_create_arm_neon ();
|
||||
#endif
|
||||
#ifdef USE_ARM_SIMD
|
||||
if (pixman_have_arm_simd ())
|
||||
return _pixman_implementation_create_arm_simd ();
|
||||
#endif
|
||||
#ifdef USE_VMX
|
||||
if (pixman_have_vmx ())
|
||||
return _pixman_implementation_create_vmx ();
|
||||
#endif
|
||||
|
||||
return _pixman_implementation_create_fast_path ();
|
||||
}
|
||||
|
@ -374,6 +374,7 @@ pixman_rasterize_edges (pixman_image_t *image,
|
||||
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);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,451 +0,0 @@
|
||||
/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Author: Keith Packard, SuSE, Inc.
|
||||
*/
|
||||
|
||||
#ifndef PIXMAN_FAST_PATH_H__
|
||||
#define PIXMAN_FAST_PATH_H__
|
||||
|
||||
#include "pixman-private.h"
|
||||
|
||||
#define PIXMAN_REPEAT_COVER -1
|
||||
|
||||
static force_inline pixman_bool_t
|
||||
repeat (pixman_repeat_t repeat, int *c, int size)
|
||||
{
|
||||
if (repeat == PIXMAN_REPEAT_NONE)
|
||||
{
|
||||
if (*c < 0 || *c >= size)
|
||||
return FALSE;
|
||||
}
|
||||
else if (repeat == PIXMAN_REPEAT_NORMAL)
|
||||
{
|
||||
while (*c >= size)
|
||||
*c -= size;
|
||||
while (*c < 0)
|
||||
*c += size;
|
||||
}
|
||||
else if (repeat == PIXMAN_REPEAT_PAD)
|
||||
{
|
||||
*c = CLIP (*c, 0, size - 1);
|
||||
}
|
||||
else /* REFLECT */
|
||||
{
|
||||
*c = MOD (*c, size * 2);
|
||||
if (*c >= size)
|
||||
*c = size * 2 - *c - 1;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* For each scanline fetched from source image with PAD repeat:
|
||||
* - calculate how many pixels need to be padded on the left side
|
||||
* - calculate how many pixels need to be padded on the right side
|
||||
* - update width to only count pixels which are fetched from the image
|
||||
* All this information is returned via 'width', 'left_pad', 'right_pad'
|
||||
* arguments. The code is assuming that 'unit_x' is positive.
|
||||
*
|
||||
* Note: 64-bit math is used in order to avoid potential overflows, which
|
||||
* is probably excessive in many cases. This particular function
|
||||
* may need its own correctness test and performance tuning.
|
||||
*/
|
||||
static force_inline void
|
||||
pad_repeat_get_scanline_bounds (int32_t source_image_width,
|
||||
pixman_fixed_t vx,
|
||||
pixman_fixed_t unit_x,
|
||||
int32_t * width,
|
||||
int32_t * left_pad,
|
||||
int32_t * right_pad)
|
||||
{
|
||||
int64_t max_vx = (int64_t) source_image_width << 16;
|
||||
int64_t tmp;
|
||||
if (vx < 0)
|
||||
{
|
||||
tmp = ((int64_t) unit_x - 1 - vx) / unit_x;
|
||||
if (tmp > *width)
|
||||
{
|
||||
*left_pad = *width;
|
||||
*width = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*left_pad = (int32_t) tmp;
|
||||
*width -= (int32_t) tmp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*left_pad = 0;
|
||||
}
|
||||
tmp = ((int64_t) unit_x - 1 - vx + max_vx) / unit_x - *left_pad;
|
||||
if (tmp < 0)
|
||||
{
|
||||
*right_pad = *width;
|
||||
*width = 0;
|
||||
}
|
||||
else if (tmp >= *width)
|
||||
{
|
||||
*right_pad = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*right_pad = *width - (int32_t) tmp;
|
||||
*width = (int32_t) tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/* A macroified version of specialized nearest scalers for some
|
||||
* common 8888 and 565 formats. It supports SRC and OVER ops.
|
||||
*
|
||||
* There are two repeat versions, one that handles repeat normal,
|
||||
* and one without repeat handling that only works if the src region
|
||||
* used is completely covered by the pre-repeated source samples.
|
||||
*
|
||||
* The loops are unrolled to process two pixels per iteration for better
|
||||
* performance on most CPU architectures (superscalar processors
|
||||
* can issue several operations simultaneously, other processors can hide
|
||||
* instructions latencies by pipelining operations). Unrolling more
|
||||
* does not make much sense because the compiler will start running out
|
||||
* of spare registers soon.
|
||||
*/
|
||||
|
||||
#define GET_8888_ALPHA(s) ((s) >> 24)
|
||||
/* This is not actually used since we don't have an OVER with
|
||||
565 source, but it is needed to build. */
|
||||
#define GET_0565_ALPHA(s) 0xff
|
||||
|
||||
#define FAST_NEAREST_SCANLINE(scanline_func_name, SRC_FORMAT, DST_FORMAT, \
|
||||
src_type_t, dst_type_t, OP, repeat_mode) \
|
||||
static force_inline void \
|
||||
scanline_func_name (dst_type_t *dst, \
|
||||
src_type_t *src, \
|
||||
int32_t w, \
|
||||
pixman_fixed_t vx, \
|
||||
pixman_fixed_t unit_x, \
|
||||
pixman_fixed_t max_vx) \
|
||||
{ \
|
||||
uint32_t d; \
|
||||
src_type_t s1, s2; \
|
||||
uint8_t a1, a2; \
|
||||
int x1, x2; \
|
||||
\
|
||||
if (PIXMAN_OP_ ## OP != PIXMAN_OP_SRC && PIXMAN_OP_ ## OP != PIXMAN_OP_OVER) \
|
||||
abort(); \
|
||||
\
|
||||
while ((w -= 2) >= 0) \
|
||||
{ \
|
||||
x1 = vx >> 16; \
|
||||
vx += unit_x; \
|
||||
if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \
|
||||
{ \
|
||||
/* This works because we know that unit_x is positive */ \
|
||||
while (vx >= max_vx) \
|
||||
vx -= max_vx; \
|
||||
} \
|
||||
s1 = src[x1]; \
|
||||
\
|
||||
x2 = vx >> 16; \
|
||||
vx += unit_x; \
|
||||
if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \
|
||||
{ \
|
||||
/* This works because we know that unit_x is positive */ \
|
||||
while (vx >= max_vx) \
|
||||
vx -= max_vx; \
|
||||
} \
|
||||
s2 = src[x2]; \
|
||||
\
|
||||
if (PIXMAN_OP_ ## OP == PIXMAN_OP_OVER) \
|
||||
{ \
|
||||
a1 = GET_ ## SRC_FORMAT ## _ALPHA(s1); \
|
||||
a2 = GET_ ## SRC_FORMAT ## _ALPHA(s2); \
|
||||
\
|
||||
if (a1 == 0xff) \
|
||||
{ \
|
||||
*dst = CONVERT_ ## SRC_FORMAT ## _TO_ ## DST_FORMAT (s1); \
|
||||
} \
|
||||
else if (s1) \
|
||||
{ \
|
||||
d = CONVERT_ ## DST_FORMAT ## _TO_8888 (*dst); \
|
||||
s1 = CONVERT_ ## SRC_FORMAT ## _TO_8888 (s1); \
|
||||
a1 ^= 0xff; \
|
||||
UN8x4_MUL_UN8_ADD_UN8x4 (d, a1, s1); \
|
||||
*dst = CONVERT_8888_TO_ ## DST_FORMAT (d); \
|
||||
} \
|
||||
dst++; \
|
||||
\
|
||||
if (a2 == 0xff) \
|
||||
{ \
|
||||
*dst = CONVERT_ ## SRC_FORMAT ## _TO_ ## DST_FORMAT (s2); \
|
||||
} \
|
||||
else if (s2) \
|
||||
{ \
|
||||
d = CONVERT_## DST_FORMAT ## _TO_8888 (*dst); \
|
||||
s2 = CONVERT_## SRC_FORMAT ## _TO_8888 (s2); \
|
||||
a2 ^= 0xff; \
|
||||
UN8x4_MUL_UN8_ADD_UN8x4 (d, a2, s2); \
|
||||
*dst = CONVERT_8888_TO_ ## DST_FORMAT (d); \
|
||||
} \
|
||||
dst++; \
|
||||
} \
|
||||
else /* PIXMAN_OP_SRC */ \
|
||||
{ \
|
||||
*dst++ = CONVERT_ ## SRC_FORMAT ## _TO_ ## DST_FORMAT (s1); \
|
||||
*dst++ = CONVERT_ ## SRC_FORMAT ## _TO_ ## DST_FORMAT (s2); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if (w & 1) \
|
||||
{ \
|
||||
x1 = vx >> 16; \
|
||||
s1 = src[x1]; \
|
||||
\
|
||||
if (PIXMAN_OP_ ## OP == PIXMAN_OP_OVER) \
|
||||
{ \
|
||||
a1 = GET_ ## SRC_FORMAT ## _ALPHA(s1); \
|
||||
\
|
||||
if (a1 == 0xff) \
|
||||
{ \
|
||||
*dst = CONVERT_ ## SRC_FORMAT ## _TO_ ## DST_FORMAT (s1); \
|
||||
} \
|
||||
else if (s1) \
|
||||
{ \
|
||||
d = CONVERT_## DST_FORMAT ## _TO_8888 (*dst); \
|
||||
s1 = CONVERT_ ## SRC_FORMAT ## _TO_8888 (s1); \
|
||||
a1 ^= 0xff; \
|
||||
UN8x4_MUL_UN8_ADD_UN8x4 (d, a1, s1); \
|
||||
*dst = CONVERT_8888_TO_ ## DST_FORMAT (d); \
|
||||
} \
|
||||
dst++; \
|
||||
} \
|
||||
else /* PIXMAN_OP_SRC */ \
|
||||
{ \
|
||||
*dst++ = CONVERT_ ## SRC_FORMAT ## _TO_ ## DST_FORMAT (s1); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define FAST_NEAREST_MAINLOOP_INT(scale_func_name, scanline_func, src_type_t, dst_type_t, \
|
||||
repeat_mode) \
|
||||
static void \
|
||||
fast_composite_scaled_nearest ## scale_func_name (pixman_implementation_t *imp, \
|
||||
pixman_op_t op, \
|
||||
pixman_image_t * src_image, \
|
||||
pixman_image_t * mask_image, \
|
||||
pixman_image_t * dst_image, \
|
||||
int32_t src_x, \
|
||||
int32_t src_y, \
|
||||
int32_t mask_x, \
|
||||
int32_t mask_y, \
|
||||
int32_t dst_x, \
|
||||
int32_t dst_y, \
|
||||
int32_t width, \
|
||||
int32_t height) \
|
||||
{ \
|
||||
dst_type_t *dst_line; \
|
||||
src_type_t *src_first_line; \
|
||||
int y; \
|
||||
pixman_fixed_t max_vx = max_vx; /* suppress uninitialized variable warning */ \
|
||||
pixman_fixed_t max_vy; \
|
||||
pixman_vector_t v; \
|
||||
pixman_fixed_t vx, vy; \
|
||||
pixman_fixed_t unit_x, unit_y; \
|
||||
int32_t left_pad, right_pad; \
|
||||
\
|
||||
src_type_t *src; \
|
||||
dst_type_t *dst; \
|
||||
int src_stride, dst_stride; \
|
||||
\
|
||||
PIXMAN_IMAGE_GET_LINE (dst_image, dst_x, dst_y, dst_type_t, dst_stride, dst_line, 1); \
|
||||
/* pass in 0 instead of src_x and src_y because src_x and src_y need to be \
|
||||
* transformed from destination space to source space */ \
|
||||
PIXMAN_IMAGE_GET_LINE (src_image, 0, 0, src_type_t, src_stride, src_first_line, 1); \
|
||||
\
|
||||
/* reference point is the center of the pixel */ \
|
||||
v.vector[0] = pixman_int_to_fixed (src_x) + pixman_fixed_1 / 2; \
|
||||
v.vector[1] = pixman_int_to_fixed (src_y) + pixman_fixed_1 / 2; \
|
||||
v.vector[2] = pixman_fixed_1; \
|
||||
\
|
||||
if (!pixman_transform_point_3d (src_image->common.transform, &v)) \
|
||||
return; \
|
||||
\
|
||||
unit_x = src_image->common.transform->matrix[0][0]; \
|
||||
unit_y = src_image->common.transform->matrix[1][1]; \
|
||||
\
|
||||
/* Round down to closest integer, ensuring that 0.5 rounds to 0, not 1 */ \
|
||||
v.vector[0] -= pixman_fixed_e; \
|
||||
v.vector[1] -= pixman_fixed_e; \
|
||||
\
|
||||
vx = v.vector[0]; \
|
||||
vy = v.vector[1]; \
|
||||
\
|
||||
if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \
|
||||
{ \
|
||||
/* Clamp repeating positions inside the actual samples */ \
|
||||
max_vx = src_image->bits.width << 16; \
|
||||
max_vy = src_image->bits.height << 16; \
|
||||
\
|
||||
repeat (PIXMAN_REPEAT_NORMAL, &vx, max_vx); \
|
||||
repeat (PIXMAN_REPEAT_NORMAL, &vy, max_vy); \
|
||||
} \
|
||||
\
|
||||
if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD || \
|
||||
PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NONE) \
|
||||
{ \
|
||||
pad_repeat_get_scanline_bounds (src_image->bits.width, vx, unit_x, \
|
||||
&width, &left_pad, &right_pad); \
|
||||
vx += left_pad * unit_x; \
|
||||
} \
|
||||
\
|
||||
while (--height >= 0) \
|
||||
{ \
|
||||
dst = dst_line; \
|
||||
dst_line += dst_stride; \
|
||||
\
|
||||
y = vy >> 16; \
|
||||
vy += unit_y; \
|
||||
if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \
|
||||
repeat (PIXMAN_REPEAT_NORMAL, &vy, max_vy); \
|
||||
if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD) \
|
||||
{ \
|
||||
repeat (PIXMAN_REPEAT_PAD, &y, src_image->bits.height); \
|
||||
src = src_first_line + src_stride * y; \
|
||||
if (left_pad > 0) \
|
||||
{ \
|
||||
scanline_func (dst, src, left_pad, 0, 0, 0); \
|
||||
} \
|
||||
if (width > 0) \
|
||||
{ \
|
||||
scanline_func (dst + left_pad, src, width, vx, unit_x, 0); \
|
||||
} \
|
||||
if (right_pad > 0) \
|
||||
{ \
|
||||
scanline_func (dst + left_pad + width, src + src_image->bits.width - 1, \
|
||||
right_pad, 0, 0, 0); \
|
||||
} \
|
||||
} \
|
||||
else if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NONE) \
|
||||
{ \
|
||||
static src_type_t zero = 0; \
|
||||
if (y < 0 || y >= src_image->bits.height) \
|
||||
{ \
|
||||
scanline_func (dst, &zero, left_pad + width + right_pad, 0, 0, 0); \
|
||||
continue; \
|
||||
} \
|
||||
src = src_first_line + src_stride * y; \
|
||||
if (left_pad > 0) \
|
||||
{ \
|
||||
scanline_func (dst, &zero, left_pad, 0, 0, 0); \
|
||||
} \
|
||||
if (width > 0) \
|
||||
{ \
|
||||
scanline_func (dst + left_pad, src, width, vx, unit_x, 0); \
|
||||
} \
|
||||
if (right_pad > 0) \
|
||||
{ \
|
||||
scanline_func (dst + left_pad + width, &zero, right_pad, 0, 0, 0); \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
src = src_first_line + src_stride * y; \
|
||||
scanline_func (dst, src, width, vx, unit_x, max_vx); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
/* A workaround for old sun studio, see: https://bugs.freedesktop.org/show_bug.cgi?id=32764 */
|
||||
#define FAST_NEAREST_MAINLOOP(scale_func_name, scanline_func, src_type_t, dst_type_t, \
|
||||
repeat_mode) \
|
||||
FAST_NEAREST_MAINLOOP_INT(_ ## scale_func_name, scanline_func, src_type_t, dst_type_t, \
|
||||
repeat_mode) \
|
||||
|
||||
#define FAST_NEAREST(scale_func_name, SRC_FORMAT, DST_FORMAT, \
|
||||
src_type_t, dst_type_t, OP, repeat_mode) \
|
||||
FAST_NEAREST_SCANLINE(scaled_nearest_scanline_ ## scale_func_name ## _ ## OP, \
|
||||
SRC_FORMAT, DST_FORMAT, src_type_t, dst_type_t, \
|
||||
OP, repeat_mode) \
|
||||
FAST_NEAREST_MAINLOOP_INT(_ ## scale_func_name ## _ ## OP, \
|
||||
scaled_nearest_scanline_ ## scale_func_name ## _ ## OP, \
|
||||
src_type_t, dst_type_t, repeat_mode) \
|
||||
\
|
||||
extern int no_such_variable
|
||||
|
||||
|
||||
#define SCALED_NEAREST_FLAGS \
|
||||
(FAST_PATH_SCALE_TRANSFORM | \
|
||||
FAST_PATH_NO_ALPHA_MAP | \
|
||||
FAST_PATH_NEAREST_FILTER | \
|
||||
FAST_PATH_NO_ACCESSORS | \
|
||||
FAST_PATH_NARROW_FORMAT)
|
||||
|
||||
#define SIMPLE_NEAREST_FAST_PATH_NORMAL(op,s,d,func) \
|
||||
{ PIXMAN_OP_ ## op, \
|
||||
PIXMAN_ ## s, \
|
||||
(SCALED_NEAREST_FLAGS | \
|
||||
FAST_PATH_NORMAL_REPEAT | \
|
||||
FAST_PATH_X_UNIT_POSITIVE), \
|
||||
PIXMAN_null, 0, \
|
||||
PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \
|
||||
fast_composite_scaled_nearest_ ## func ## _normal ## _ ## op, \
|
||||
}
|
||||
|
||||
#define SIMPLE_NEAREST_FAST_PATH_PAD(op,s,d,func) \
|
||||
{ PIXMAN_OP_ ## op, \
|
||||
PIXMAN_ ## s, \
|
||||
(SCALED_NEAREST_FLAGS | \
|
||||
FAST_PATH_PAD_REPEAT | \
|
||||
FAST_PATH_X_UNIT_POSITIVE), \
|
||||
PIXMAN_null, 0, \
|
||||
PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \
|
||||
fast_composite_scaled_nearest_ ## func ## _pad ## _ ## op, \
|
||||
}
|
||||
|
||||
#define SIMPLE_NEAREST_FAST_PATH_NONE(op,s,d,func) \
|
||||
{ PIXMAN_OP_ ## op, \
|
||||
PIXMAN_ ## s, \
|
||||
(SCALED_NEAREST_FLAGS | \
|
||||
FAST_PATH_NONE_REPEAT | \
|
||||
FAST_PATH_X_UNIT_POSITIVE), \
|
||||
PIXMAN_null, 0, \
|
||||
PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \
|
||||
fast_composite_scaled_nearest_ ## func ## _none ## _ ## op, \
|
||||
}
|
||||
|
||||
#define SIMPLE_NEAREST_FAST_PATH_COVER(op,s,d,func) \
|
||||
{ PIXMAN_OP_ ## op, \
|
||||
PIXMAN_ ## s, \
|
||||
SCALED_NEAREST_FLAGS | FAST_PATH_SAMPLES_COVER_CLIP, \
|
||||
PIXMAN_null, 0, \
|
||||
PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \
|
||||
fast_composite_scaled_nearest_ ## func ## _cover ## _ ## op, \
|
||||
}
|
||||
|
||||
/* Prefer the use of 'cover' variant, because it is faster */
|
||||
#define 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)
|
||||
|
||||
#endif
|
350
programs/develop/libraries/pixman/pixman-filter.c
Normal file
350
programs/develop/libraries/pixman/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;
|
||||
}
|
@ -36,44 +36,102 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "pixman-private.h"
|
||||
#include "pixman-combine32.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_op_t op,
|
||||
pixman_image_t * src,
|
||||
pixman_image_t * mask,
|
||||
pixman_image_t * dest,
|
||||
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_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;
|
||||
fetch_scanline_t fetch_src = NULL, fetch_mask = NULL, fetch_dest = NULL;
|
||||
pixman_iter_t src_iter, mask_iter, dest_iter;
|
||||
pixman_combine_32_func_t compose;
|
||||
store_scanline_t store;
|
||||
source_image_class_t src_class, mask_class;
|
||||
pixman_bool_t component_alpha;
|
||||
uint32_t *bits;
|
||||
int32_t stride;
|
||||
int narrow, Bpp;
|
||||
iter_flags_t narrow, src_iter_flags;
|
||||
int Bpp;
|
||||
int i;
|
||||
|
||||
narrow =
|
||||
(src->common.flags & FAST_PATH_NARROW_FORMAT) &&
|
||||
(!mask || mask->common.flags & FAST_PATH_NARROW_FORMAT) &&
|
||||
(dest->common.flags & FAST_PATH_NARROW_FORMAT);
|
||||
Bpp = narrow ? 4 : 8;
|
||||
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;
|
||||
}
|
||||
|
||||
if (width * Bpp > SCANLINE_BUFFER_LENGTH)
|
||||
{
|
||||
@ -87,172 +145,60 @@ general_composite_rect (pixman_implementation_t *imp,
|
||||
mask_buffer = src_buffer + width * Bpp;
|
||||
dest_buffer = mask_buffer + width * Bpp;
|
||||
|
||||
src_class = _pixman_image_classify (src,
|
||||
src_x, src_y,
|
||||
width, height);
|
||||
|
||||
mask_class = SOURCE_IMAGE_CLASS_UNKNOWN;
|
||||
|
||||
if (mask)
|
||||
if (!narrow)
|
||||
{
|
||||
mask_class = _pixman_image_classify (mask,
|
||||
src_x, src_y,
|
||||
width, height);
|
||||
/* 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;
|
||||
|
||||
if (op == PIXMAN_OP_CLEAR)
|
||||
fetch_src = NULL;
|
||||
else if (narrow)
|
||||
fetch_src = _pixman_image_get_scanline_32;
|
||||
else
|
||||
fetch_src = _pixman_image_get_scanline_64;
|
||||
_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);
|
||||
|
||||
if (!mask || op == PIXMAN_OP_CLEAR)
|
||||
fetch_mask = NULL;
|
||||
else if (narrow)
|
||||
fetch_mask = _pixman_image_get_scanline_32;
|
||||
else
|
||||
fetch_mask = _pixman_image_get_scanline_64;
|
||||
|
||||
if (op == PIXMAN_OP_CLEAR || op == PIXMAN_OP_SRC)
|
||||
fetch_dest = NULL;
|
||||
else if (narrow)
|
||||
fetch_dest = _pixman_image_get_scanline_32;
|
||||
else
|
||||
fetch_dest = _pixman_image_get_scanline_64;
|
||||
|
||||
if (narrow)
|
||||
store = _pixman_image_store_scanline_32;
|
||||
else
|
||||
store = _pixman_image_store_scanline_64;
|
||||
|
||||
/* Skip the store step and composite directly into the
|
||||
* destination if the output format of the compose func matches
|
||||
* the destination format.
|
||||
*
|
||||
* If the destination format is a8r8g8b8 then we can always do
|
||||
* this. If it is x8r8g8b8, then we can only do it if the
|
||||
* operator doesn't make use of destination alpha.
|
||||
*/
|
||||
if ((dest->bits.format == PIXMAN_a8r8g8b8) ||
|
||||
(dest->bits.format == PIXMAN_x8r8g8b8 &&
|
||||
(op == PIXMAN_OP_OVER ||
|
||||
op == PIXMAN_OP_ADD ||
|
||||
op == PIXMAN_OP_SRC ||
|
||||
op == PIXMAN_OP_CLEAR ||
|
||||
op == PIXMAN_OP_IN_REVERSE ||
|
||||
op == PIXMAN_OP_OUT_REVERSE ||
|
||||
op == PIXMAN_OP_DST)))
|
||||
/* mask iter */
|
||||
if ((src_iter_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) ==
|
||||
(ITER_IGNORE_ALPHA | ITER_IGNORE_RGB))
|
||||
{
|
||||
if (narrow &&
|
||||
!dest->common.alpha_map &&
|
||||
!dest->bits.write_func)
|
||||
{
|
||||
store = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!store)
|
||||
{
|
||||
bits = dest->bits.bits;
|
||||
stride = dest->bits.rowstride;
|
||||
}
|
||||
else
|
||||
{
|
||||
bits = NULL;
|
||||
stride = 0;
|
||||
/* If it doesn't matter what the source is, then it doesn't matter
|
||||
* what the mask is
|
||||
*/
|
||||
mask_image = NULL;
|
||||
}
|
||||
|
||||
component_alpha =
|
||||
fetch_src &&
|
||||
fetch_mask &&
|
||||
mask &&
|
||||
mask->common.type == BITS &&
|
||||
mask->common.component_alpha &&
|
||||
PIXMAN_FORMAT_RGB (mask->bits.format);
|
||||
mask_image &&
|
||||
mask_image->common.type == BITS &&
|
||||
mask_image->common.component_alpha &&
|
||||
PIXMAN_FORMAT_RGB (mask_image->bits.format);
|
||||
|
||||
if (narrow)
|
||||
{
|
||||
if (component_alpha)
|
||||
compose = _pixman_implementation_combine_32_ca;
|
||||
else
|
||||
compose = _pixman_implementation_combine_32;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (component_alpha)
|
||||
compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64_ca;
|
||||
else
|
||||
compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64;
|
||||
}
|
||||
_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);
|
||||
|
||||
if (!compose)
|
||||
return;
|
||||
/* 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, info->dest_flags);
|
||||
|
||||
if (!fetch_mask)
|
||||
mask_buffer = NULL;
|
||||
compose = _pixman_implementation_lookup_combiner (
|
||||
imp->toplevel, op, component_alpha, narrow);
|
||||
|
||||
for (i = 0; i < height; ++i)
|
||||
{
|
||||
/* fill first half of scanline with source */
|
||||
if (fetch_src)
|
||||
{
|
||||
if (fetch_mask)
|
||||
{
|
||||
/* fetch mask before source so that fetching of
|
||||
source can be optimized */
|
||||
fetch_mask (mask, mask_x, mask_y + i,
|
||||
width, (void *)mask_buffer, 0);
|
||||
uint32_t *s, *m, *d;
|
||||
|
||||
if (mask_class == SOURCE_IMAGE_CLASS_HORIZONTAL)
|
||||
fetch_mask = NULL;
|
||||
}
|
||||
m = mask_iter.get_scanline (&mask_iter, NULL);
|
||||
s = src_iter.get_scanline (&src_iter, m);
|
||||
d = dest_iter.get_scanline (&dest_iter, NULL);
|
||||
|
||||
if (src_class == SOURCE_IMAGE_CLASS_HORIZONTAL)
|
||||
{
|
||||
fetch_src (src, src_x, src_y + i,
|
||||
width, (void *)src_buffer, 0);
|
||||
fetch_src = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
fetch_src (src, src_x, src_y + i,
|
||||
width, (void *)src_buffer, (void *)mask_buffer);
|
||||
}
|
||||
}
|
||||
else if (fetch_mask)
|
||||
{
|
||||
fetch_mask (mask, mask_x, mask_y + i,
|
||||
width, (void *)mask_buffer, 0);
|
||||
}
|
||||
compose (imp->toplevel, op, d, s, m, width);
|
||||
|
||||
if (store)
|
||||
{
|
||||
/* fill dest into second half of scanline */
|
||||
if (fetch_dest)
|
||||
{
|
||||
fetch_dest (dest, dest_x, dest_y + i,
|
||||
width, (void *)dest_buffer, 0);
|
||||
}
|
||||
|
||||
/* blend */
|
||||
compose (imp->toplevel, op,
|
||||
(void *)dest_buffer,
|
||||
(void *)src_buffer,
|
||||
(void *)mask_buffer,
|
||||
width);
|
||||
|
||||
/* write back */
|
||||
store (&(dest->bits), dest_x, dest_y + i, width,
|
||||
(void *)dest_buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* blend */
|
||||
compose (imp->toplevel, op,
|
||||
bits + (dest_y + i) * stride + dest_x,
|
||||
(void *)src_buffer, (void *)mask_buffer, width);
|
||||
}
|
||||
dest_iter.write_back (&dest_iter);
|
||||
}
|
||||
|
||||
if (scanline_buffer != (uint8_t *) stack_scanline_buffer)
|
||||
@ -265,50 +211,16 @@ static const pixman_fast_path_t general_fast_path[] =
|
||||
{ PIXMAN_OP_NONE }
|
||||
};
|
||||
|
||||
static pixman_bool_t
|
||||
general_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 dst_x,
|
||||
int dst_y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
/* We can't blit unless we have sse2 or mmx */
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static pixman_bool_t
|
||||
general_fill (pixman_implementation_t *imp,
|
||||
uint32_t * bits,
|
||||
int stride,
|
||||
int bpp,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
uint32_t xor)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pixman_implementation_t *
|
||||
_pixman_implementation_create_general (void)
|
||||
{
|
||||
pixman_implementation_t *imp = _pixman_implementation_create (NULL, general_fast_path);
|
||||
|
||||
_pixman_setup_combiner_functions_32 (imp);
|
||||
_pixman_setup_combiner_functions_64 (imp);
|
||||
_pixman_setup_combiner_functions_float (imp);
|
||||
|
||||
imp->blt = general_blt;
|
||||
imp->fill = general_fill;
|
||||
imp->src_iter_init = general_src_iter_init;
|
||||
imp->dest_iter_init = general_dest_iter_init;
|
||||
|
||||
return imp;
|
||||
}
|
||||
|
670
programs/develop/libraries/pixman/pixman-glyph.c
Normal file
670
programs/develop/libraries/pixman/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);
|
||||
}
|
@ -31,123 +31,71 @@
|
||||
void
|
||||
_pixman_gradient_walker_init (pixman_gradient_walker_t *walker,
|
||||
gradient_t * gradient,
|
||||
unsigned int spread)
|
||||
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->spread = spread;
|
||||
walker->a_s = 0.0f;
|
||||
walker->a_b = 0.0f;
|
||||
walker->r_s = 0.0f;
|
||||
walker->r_b = 0.0f;
|
||||
walker->g_s = 0.0f;
|
||||
walker->g_b = 0.0f;
|
||||
walker->b_s = 0.0f;
|
||||
walker->b_b = 0.0f;
|
||||
walker->repeat = repeat;
|
||||
|
||||
walker->need_reset = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
_pixman_gradient_walker_reset (pixman_gradient_walker_t *walker,
|
||||
pixman_fixed_32_32_t pos)
|
||||
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;
|
||||
pixman_color_t *left_c, *right_c;
|
||||
int n, count = walker->num_stops;
|
||||
pixman_gradient_stop_t * stops = walker->stops;
|
||||
pixman_gradient_stop_t *stops = walker->stops;
|
||||
float la, lr, lg, lb;
|
||||
float ra, rr, rg, rb;
|
||||
float lx, rx;
|
||||
|
||||
static const pixman_color_t transparent_black = { 0, 0, 0, 0 };
|
||||
|
||||
switch (walker->spread)
|
||||
if (walker->repeat == PIXMAN_REPEAT_NORMAL)
|
||||
{
|
||||
case PIXMAN_REPEAT_NORMAL:
|
||||
x = (int32_t)pos & 0xFFFF;
|
||||
for (n = 0; n < count; n++)
|
||||
if (x < stops[n].x)
|
||||
break;
|
||||
if (n == 0)
|
||||
{
|
||||
left_x = stops[count - 1].x - 0x10000;
|
||||
left_c = &stops[count - 1].color;
|
||||
}
|
||||
else
|
||||
{
|
||||
left_x = stops[n - 1].x;
|
||||
left_c = &stops[n - 1].color;
|
||||
}
|
||||
|
||||
if (n == count)
|
||||
{
|
||||
right_x = stops[0].x + 0x10000;
|
||||
right_c = &stops[0].color;
|
||||
}
|
||||
else
|
||||
{
|
||||
right_x = stops[n].x;
|
||||
right_c = &stops[n].color;
|
||||
}
|
||||
left_x += (pos - x);
|
||||
right_x += (pos - x);
|
||||
break;
|
||||
|
||||
case PIXMAN_REPEAT_PAD:
|
||||
for (n = 0; n < count; n++)
|
||||
if (pos < stops[n].x)
|
||||
break;
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
left_x = INT32_MIN;
|
||||
left_c = &stops[0].color;
|
||||
}
|
||||
else
|
||||
{
|
||||
left_x = stops[n - 1].x;
|
||||
left_c = &stops[n - 1].color;
|
||||
}
|
||||
|
||||
if (n == count)
|
||||
{
|
||||
right_x = INT32_MAX;
|
||||
right_c = &stops[n - 1].color;
|
||||
}
|
||||
else
|
||||
{
|
||||
right_x = stops[n].x;
|
||||
right_c = &stops[n].color;
|
||||
}
|
||||
break;
|
||||
|
||||
case PIXMAN_REPEAT_REFLECT:
|
||||
x = (int32_t)pos & 0xFFFF;
|
||||
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;
|
||||
for (n = 0; n < count; n++)
|
||||
if (x < stops[n].x)
|
||||
break;
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
left_x = -stops[0].x;
|
||||
left_c = &stops[0].color;
|
||||
}
|
||||
else
|
||||
{
|
||||
left_x = stops[n - 1].x;
|
||||
left_c = &stops[n - 1].color;
|
||||
}
|
||||
|
||||
if (n == count)
|
||||
{
|
||||
right_x = 0x20000 - stops[n - 1].x;
|
||||
right_c = &stops[n - 1].color;
|
||||
}
|
||||
else
|
||||
{
|
||||
right_x = stops[n].x;
|
||||
right_c = &stops[n].color;
|
||||
}
|
||||
}
|
||||
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;
|
||||
@ -165,90 +113,90 @@ _pixman_gradient_walker_reset (pixman_gradient_walker_t *walker,
|
||||
}
|
||||
left_x += (pos - x);
|
||||
right_x += (pos - x);
|
||||
break;
|
||||
|
||||
default: /* REPEAT_NONE */
|
||||
for (n = 0; n < count; n++)
|
||||
if (pos < stops[n].x)
|
||||
break;
|
||||
|
||||
}
|
||||
else if (walker->repeat == PIXMAN_REPEAT_NONE)
|
||||
{
|
||||
if (n == 0)
|
||||
{
|
||||
left_x = INT32_MIN;
|
||||
right_x = stops[0].x;
|
||||
left_c = right_c = (pixman_color_t*) &transparent_black;
|
||||
}
|
||||
right_c = left_c;
|
||||
else if (n == count)
|
||||
{
|
||||
left_x = stops[n - 1].x;
|
||||
right_x = INT32_MAX;
|
||||
left_c = right_c = (pixman_color_t*) &transparent_black;
|
||||
}
|
||||
else
|
||||
{
|
||||
left_x = stops[n - 1].x;
|
||||
right_x = stops[n].x;
|
||||
left_c = &stops[n - 1].color;
|
||||
right_c = &stops[n].color;
|
||||
}
|
||||
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);
|
||||
/* The alpha channel is scaled to be in the [0, 255] interval,
|
||||
* and the red/green/blue channels are scaled to be in [0, 1].
|
||||
* This ensures that after premultiplication all channels will
|
||||
* be in the [0, 255] interval.
|
||||
*/
|
||||
la = (left_c->alpha * (1.0f/257.0f));
|
||||
lr = (left_c->red * (1.0f/257.0f));
|
||||
lg = (left_c->green * (1.0f/257.0f));
|
||||
lb = (left_c->blue * (1.0f/257.0f));
|
||||
|
||||
if (walker->left_x == walker->right_x ||
|
||||
( walker->left_ag == walker->right_ag &&
|
||||
walker->left_rb == walker->right_rb ) )
|
||||
ra = (right_c->alpha * (1.0f/257.0f));
|
||||
rr = (right_c->red * (1.0f/257.0f));
|
||||
rg = (right_c->green * (1.0f/257.0f));
|
||||
rb = (right_c->blue * (1.0f/257.0f));
|
||||
|
||||
lx = left_x * (1.0f/65536.0f);
|
||||
rx = right_x * (1.0f/65536.0f);
|
||||
|
||||
if (FLOAT_IS_ZERO (rx - lx) || left_x == INT32_MIN || right_x == INT32_MAX)
|
||||
{
|
||||
walker->stepper = 0;
|
||||
walker->a_s = walker->r_s = walker->g_s = walker->b_s = 0.0f;
|
||||
walker->a_b = (la + ra) / 2.0f;
|
||||
walker->r_b = (lr + rr) / 510.0f;
|
||||
walker->g_b = (lg + rg) / 510.0f;
|
||||
walker->b_b = (lb + rb) / 510.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
int32_t width = right_x - left_x;
|
||||
walker->stepper = ((1 << 24) + width / 2) / width;
|
||||
float w_rec = 1.0f / (rx - lx);
|
||||
|
||||
walker->a_b = (la * rx - ra * lx) * w_rec;
|
||||
walker->r_b = (lr * rx - rr * lx) * w_rec * (1.0f/255.0f);
|
||||
walker->g_b = (lg * rx - rg * lx) * w_rec * (1.0f/255.0f);
|
||||
walker->b_b = (lb * rx - rb * lx) * w_rec * (1.0f/255.0f);
|
||||
|
||||
walker->a_s = (ra - la) * w_rec;
|
||||
walker->r_s = (rr - lr) * w_rec * (1.0f/255.0f);
|
||||
walker->g_s = (rg - lg) * w_rec * (1.0f/255.0f);
|
||||
walker->b_s = (rb - lb) * w_rec * (1.0f/255.0f);
|
||||
}
|
||||
|
||||
walker->left_x = left_x;
|
||||
walker->right_x = right_x;
|
||||
|
||||
walker->need_reset = FALSE;
|
||||
}
|
||||
|
||||
#define PIXMAN_GRADIENT_WALKER_NEED_RESET(w, x) \
|
||||
( (w)->need_reset || (x) < (w)->left_x || (x) >= (w)->right_x)
|
||||
|
||||
|
||||
/* the following assumes that PIXMAN_GRADIENT_WALKER_NEED_RESET(w,x) is FALSE */
|
||||
uint32_t
|
||||
_pixman_gradient_walker_pixel (pixman_gradient_walker_t *walker,
|
||||
pixman_fixed_32_32_t x)
|
||||
pixman_fixed_48_16_t x)
|
||||
{
|
||||
int dist, idist;
|
||||
uint32_t t1, t2, a, color;
|
||||
float a, r, g, b;
|
||||
uint8_t a8, r8, g8, b8;
|
||||
uint32_t v;
|
||||
float y;
|
||||
|
||||
if (PIXMAN_GRADIENT_WALKER_NEED_RESET (walker, x))
|
||||
_pixman_gradient_walker_reset (walker, x);
|
||||
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;
|
||||
y = x * (1.0f / 65536.0f);
|
||||
|
||||
/* combined INTERPOLATE and premultiply */
|
||||
t1 = walker->left_rb * idist + walker->right_rb * dist;
|
||||
t1 = (t1 >> 8) & 0xff00ff;
|
||||
a = walker->a_s * y + walker->a_b;
|
||||
r = a * (walker->r_s * y + walker->r_b);
|
||||
g = a * (walker->g_s * y + walker->g_b);
|
||||
b = a * (walker->b_s * y + walker->b_b);
|
||||
|
||||
t2 = walker->left_ag * idist + walker->right_ag * dist;
|
||||
t2 &= 0xff00ff00;
|
||||
a8 = a + 0.5f;
|
||||
r8 = r + 0.5f;
|
||||
g8 = g + 0.5f;
|
||||
b8 = b + 0.5f;
|
||||
|
||||
color = t2 & 0xff000000;
|
||||
a = t2 >> 24;
|
||||
v = ((a8 << 24) & 0xff000000) |
|
||||
((r8 << 16) & 0x00ff0000) |
|
||||
((g8 << 8) & 0x0000ff00) |
|
||||
((b8 >> 0) & 0x000000ff);
|
||||
|
||||
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));
|
||||
return v;
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,50 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "pixman-private.h"
|
||||
#include "pixman-combine32.h"
|
||||
|
||||
static const pixman_color_t transparent_black = { 0, 0, 0, 0 };
|
||||
|
||||
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,
|
||||
@ -39,54 +82,100 @@ _pixman_init_gradient (gradient_t * gradient,
|
||||
{
|
||||
return_val_if_fail (n_stops > 0, FALSE);
|
||||
|
||||
gradient->stops = pixman_malloc_ab (n_stops, sizeof (pixman_gradient_stop_t));
|
||||
/* 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->stop_range = 0xffff;
|
||||
gradient->common.property_changed = gradient_property_changed;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* By default, just evaluate the image at 32bpp and expand. Individual image
|
||||
* types can plug in a better scanline getter if they want to. For example
|
||||
* we could produce smoother gradients by evaluating them at higher color
|
||||
* depth, but that's a project for the future.
|
||||
*/
|
||||
void
|
||||
_pixman_image_get_scanline_generic_64 (pixman_image_t * image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
uint32_t * buffer,
|
||||
const uint32_t * mask)
|
||||
_pixman_image_init (pixman_image_t *image)
|
||||
{
|
||||
uint32_t *mask8 = NULL;
|
||||
image_common_t *common = &image->common;
|
||||
|
||||
/* Contract the mask image, if one exists, so that the 32-bit fetch
|
||||
* function can use it.
|
||||
*/
|
||||
if (mask)
|
||||
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)
|
||||
{
|
||||
mask8 = pixman_malloc_ab (width, sizeof(uint32_t));
|
||||
if (!mask8)
|
||||
return;
|
||||
if (image->common.destroy_func)
|
||||
image->common.destroy_func (image, image->common.destroy_data);
|
||||
|
||||
pixman_contract (mask8, (uint64_t *)mask, width);
|
||||
pixman_region32_fini (&common->clip_region);
|
||||
|
||||
free (common->transform);
|
||||
free (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 */
|
||||
free (image->gradient.stops - 1);
|
||||
}
|
||||
|
||||
/* 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 (image->bits.free_me);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Fetch the source image into the first half of buffer. */
|
||||
_pixman_image_get_scanline_32 (image, x, y, width, (uint32_t*)buffer, mask8);
|
||||
|
||||
/* Expand from 32bpp to 64bpp in place. */
|
||||
pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, width);
|
||||
|
||||
free (mask8);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pixman_image_t *
|
||||
@ -95,70 +184,11 @@ _pixman_image_allocate (void)
|
||||
pixman_image_t *image = malloc (sizeof (pixman_image_t));
|
||||
|
||||
if (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->classify = NULL;
|
||||
common->client_clip = FALSE;
|
||||
common->destroy_func = NULL;
|
||||
common->destroy_data = NULL;
|
||||
common->dirty = TRUE;
|
||||
}
|
||||
_pixman_image_init (image);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
source_image_class_t
|
||||
_pixman_image_classify (pixman_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
if (image->common.classify)
|
||||
return image->common.classify (image, x, y, width, height);
|
||||
else
|
||||
return SOURCE_IMAGE_CLASS_UNKNOWN;
|
||||
}
|
||||
|
||||
void
|
||||
_pixman_image_get_scanline_32 (pixman_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
uint32_t * buffer,
|
||||
const uint32_t *mask)
|
||||
{
|
||||
image->common.get_scanline_32 (image, x, y, width, buffer, mask);
|
||||
}
|
||||
|
||||
/* Even thought the type of buffer is uint32_t *, the function actually expects
|
||||
* a uint64_t *buffer.
|
||||
*/
|
||||
void
|
||||
_pixman_image_get_scanline_64 (pixman_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
uint32_t * buffer,
|
||||
const uint32_t *unused)
|
||||
{
|
||||
image->common.get_scanline_64 (image, x, y, width, buffer, unused);
|
||||
}
|
||||
|
||||
static void
|
||||
image_property_changed (pixman_image_t *image)
|
||||
{
|
||||
@ -178,39 +208,9 @@ pixman_image_ref (pixman_image_t *image)
|
||||
PIXMAN_EXPORT pixman_bool_t
|
||||
pixman_image_unref (pixman_image_t *image)
|
||||
{
|
||||
image_common_t *common = (image_common_t *)image;
|
||||
|
||||
common->ref_count--;
|
||||
|
||||
if (common->ref_count == 0)
|
||||
if (_pixman_image_fini (image))
|
||||
{
|
||||
if (image->common.destroy_func)
|
||||
image->common.destroy_func (image, image->common.destroy_data);
|
||||
|
||||
pixman_region32_fini (&common->clip_region);
|
||||
|
||||
if (common->transform)
|
||||
free (common->transform);
|
||||
|
||||
if (common->filter_params)
|
||||
free (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)
|
||||
free (image->gradient.stops);
|
||||
}
|
||||
|
||||
if (image->type == BITS && image->bits.free_me)
|
||||
free (image->bits.free_me);
|
||||
|
||||
free (image);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -238,54 +238,27 @@ _pixman_image_reset_clip_region (pixman_image_t *image)
|
||||
image->common.have_clip_region = FALSE;
|
||||
}
|
||||
|
||||
static pixman_bool_t out_of_bounds_workaround = TRUE;
|
||||
|
||||
/* Old X servers rely on out-of-bounds accesses when they are asked
|
||||
* to composite with a window as the source. They create a pixman image
|
||||
* pointing to some bogus position in memory, but then they set a clip
|
||||
* region to the position where the actual bits are.
|
||||
/* 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 by default we allow certain out-of-bound access
|
||||
* to happen unless explicitly disabled.
|
||||
* 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.
|
||||
*
|
||||
* Fixed X servers should call this function to disable the workaround.
|
||||
* 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)
|
||||
{
|
||||
out_of_bounds_workaround = FALSE;
|
||||
}
|
||||
|
||||
static pixman_bool_t
|
||||
source_image_needs_out_of_bounds_workaround (bits_image_t *image)
|
||||
{
|
||||
if (image->common.clip_sources &&
|
||||
image->common.repeat == PIXMAN_REPEAT_NONE &&
|
||||
image->common.have_clip_region &&
|
||||
out_of_bounds_workaround)
|
||||
{
|
||||
if (!image->common.client_clip)
|
||||
{
|
||||
/* There is no client clip, so if the clip region extends beyond the
|
||||
* drawable geometry, it must be because the X server generated the
|
||||
* bogus clip region.
|
||||
*/
|
||||
const pixman_box32_t *extents =
|
||||
pixman_region32_extents (&image->common.clip_region);
|
||||
|
||||
if (extents->x1 >= 0 && extents->x2 <= image->width &&
|
||||
extents->y1 >= 0 && extents->y2 <= image->height)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -315,8 +288,24 @@ compute_image_info (pixman_image_t *image)
|
||||
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)
|
||||
@ -338,11 +327,56 @@ compute_image_info (pixman_image_t *image)
|
||||
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;
|
||||
@ -408,6 +442,7 @@ compute_image_info (pixman_image_t *image)
|
||||
else
|
||||
{
|
||||
code = image->bits.format;
|
||||
flags |= FAST_PATH_BITS_IMAGE;
|
||||
}
|
||||
|
||||
if (!PIXMAN_FORMAT_A (image->bits.format) &&
|
||||
@ -420,9 +455,6 @@ compute_image_info (pixman_image_t *image)
|
||||
flags |= FAST_PATH_IS_OPAQUE;
|
||||
}
|
||||
|
||||
if (source_image_needs_out_of_bounds_workaround (&image->bits))
|
||||
flags |= FAST_PATH_NEEDS_WORKAROUND;
|
||||
|
||||
if (image->bits.read_func || image->bits.write_func)
|
||||
flags &= ~FAST_PATH_NO_ACCESSORS;
|
||||
|
||||
@ -445,6 +477,7 @@ compute_image_info (pixman_image_t *image)
|
||||
|
||||
/* Fall through */
|
||||
|
||||
case CONICAL:
|
||||
case LINEAR:
|
||||
code = PIXMAN_unknown;
|
||||
|
||||
@ -486,8 +519,9 @@ compute_image_info (pixman_image_t *image)
|
||||
* 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 ||
|
||||
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);
|
||||
@ -509,7 +543,8 @@ _pixman_image_validate (pixman_image_t *image)
|
||||
* property_changed() can make use of the flags
|
||||
* to set up accessors etc.
|
||||
*/
|
||||
image->common.property_changed (image);
|
||||
if (image->common.property_changed)
|
||||
image->common.property_changed (image);
|
||||
|
||||
image->common.dirty = FALSE;
|
||||
}
|
||||
@ -590,7 +625,7 @@ pixman_image_set_transform (pixman_image_t * image,
|
||||
if (common->transform == transform)
|
||||
return TRUE;
|
||||
|
||||
if (memcmp (&id, transform, sizeof (pixman_transform_t)) == 0)
|
||||
if (!transform || memcmp (&id, transform, sizeof (pixman_transform_t)) == 0)
|
||||
{
|
||||
free (common->transform);
|
||||
common->transform = NULL;
|
||||
@ -599,6 +634,12 @@ pixman_image_set_transform (pixman_image_t * image,
|
||||
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));
|
||||
|
||||
@ -623,6 +664,9 @@ 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);
|
||||
@ -640,6 +684,19 @@ pixman_image_set_filter (pixman_image_t * image,
|
||||
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)
|
||||
{
|
||||
@ -667,6 +724,9 @@ 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);
|
||||
@ -682,6 +742,9 @@ pixman_image_set_indexed (pixman_image_t * image,
|
||||
{
|
||||
bits_image_t *bits = (bits_image_t *)image;
|
||||
|
||||
if (bits->indexed == indexed)
|
||||
return;
|
||||
|
||||
bits->indexed = indexed;
|
||||
|
||||
image_property_changed (image);
|
||||
@ -744,6 +807,9 @@ 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);
|
||||
@ -822,19 +888,47 @@ pixman_image_get_format (pixman_image_t *image)
|
||||
if (image->type == BITS)
|
||||
return image->bits.format;
|
||||
|
||||
return 0;
|
||||
return PIXMAN_null;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
_pixman_image_get_solid (pixman_image_t * image,
|
||||
pixman_format_code_t format)
|
||||
_pixman_image_get_solid (pixman_implementation_t *imp,
|
||||
pixman_image_t * image,
|
||||
pixman_format_code_t format)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
_pixman_image_get_scanline_32 (image, 0, 0, 1, &result, NULL);
|
||||
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)
|
||||
if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB
|
||||
&& PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB_SRGB)
|
||||
{
|
||||
result = (((result & 0xff000000) >> 0) |
|
||||
((result & 0x00ff0000) >> 16) |
|
||||
|
@ -27,168 +27,206 @@
|
||||
#include <stdlib.h>
|
||||
#include "pixman-private.h"
|
||||
|
||||
static void
|
||||
delegate_combine_32 (pixman_implementation_t * imp,
|
||||
pixman_op_t op,
|
||||
uint32_t * dest,
|
||||
const uint32_t * src,
|
||||
const uint32_t * mask,
|
||||
int width)
|
||||
{
|
||||
_pixman_implementation_combine_32 (imp->delegate,
|
||||
op, dest, src, mask, width);
|
||||
}
|
||||
|
||||
static void
|
||||
delegate_combine_64 (pixman_implementation_t * imp,
|
||||
pixman_op_t op,
|
||||
uint64_t * dest,
|
||||
const uint64_t * src,
|
||||
const uint64_t * mask,
|
||||
int width)
|
||||
{
|
||||
_pixman_implementation_combine_64 (imp->delegate,
|
||||
op, dest, src, mask, width);
|
||||
}
|
||||
|
||||
static void
|
||||
delegate_combine_32_ca (pixman_implementation_t * imp,
|
||||
pixman_op_t op,
|
||||
uint32_t * dest,
|
||||
const uint32_t * src,
|
||||
const uint32_t * mask,
|
||||
int width)
|
||||
{
|
||||
_pixman_implementation_combine_32_ca (imp->delegate,
|
||||
op, dest, src, mask, width);
|
||||
}
|
||||
|
||||
static void
|
||||
delegate_combine_64_ca (pixman_implementation_t * imp,
|
||||
pixman_op_t op,
|
||||
uint64_t * dest,
|
||||
const uint64_t * src,
|
||||
const uint64_t * mask,
|
||||
int width)
|
||||
{
|
||||
_pixman_implementation_combine_64_ca (imp->delegate,
|
||||
op, dest, src, mask, width);
|
||||
}
|
||||
|
||||
static pixman_bool_t
|
||||
delegate_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 dst_x,
|
||||
int dst_y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
return _pixman_implementation_blt (
|
||||
imp->delegate, src_bits, dst_bits, src_stride, dst_stride,
|
||||
src_bpp, dst_bpp, src_x, src_y, dst_x, dst_y,
|
||||
width, height);
|
||||
}
|
||||
|
||||
static pixman_bool_t
|
||||
delegate_fill (pixman_implementation_t *imp,
|
||||
uint32_t * bits,
|
||||
int stride,
|
||||
int bpp,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
uint32_t xor)
|
||||
{
|
||||
return _pixman_implementation_fill (
|
||||
imp->delegate, bits, stride, bpp, x, y, width, height, xor);
|
||||
}
|
||||
|
||||
pixman_implementation_t *
|
||||
_pixman_implementation_create (pixman_implementation_t *delegate,
|
||||
_pixman_implementation_create (pixman_implementation_t *fallback,
|
||||
const pixman_fast_path_t *fast_paths)
|
||||
{
|
||||
pixman_implementation_t *imp = malloc (sizeof (pixman_implementation_t));
|
||||
pixman_implementation_t *d;
|
||||
int i;
|
||||
|
||||
if (!imp)
|
||||
return NULL;
|
||||
pixman_implementation_t *imp;
|
||||
|
||||
assert (fast_paths);
|
||||
|
||||
/* Make sure the whole delegate chain has the right toplevel */
|
||||
imp->delegate = delegate;
|
||||
for (d = imp; d != NULL; d = d->delegate)
|
||||
d->toplevel = imp;
|
||||
|
||||
/* Fill out function pointers with ones that just delegate
|
||||
*/
|
||||
imp->blt = delegate_blt;
|
||||
imp->fill = delegate_fill;
|
||||
|
||||
for (i = 0; i < PIXMAN_N_OPERATORS; ++i)
|
||||
if ((imp = malloc (sizeof (pixman_implementation_t))))
|
||||
{
|
||||
imp->combine_32[i] = delegate_combine_32;
|
||||
imp->combine_64[i] = delegate_combine_64;
|
||||
imp->combine_32_ca[i] = delegate_combine_32_ca;
|
||||
imp->combine_64_ca[i] = delegate_combine_64_ca;
|
||||
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;
|
||||
}
|
||||
|
||||
imp->fast_paths = fast_paths;
|
||||
|
||||
return imp;
|
||||
}
|
||||
|
||||
void
|
||||
_pixman_implementation_combine_32 (pixman_implementation_t * imp,
|
||||
pixman_op_t op,
|
||||
uint32_t * dest,
|
||||
const uint32_t * src,
|
||||
const uint32_t * mask,
|
||||
int width)
|
||||
#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)
|
||||
{
|
||||
(*imp->combine_32[op]) (imp, op, dest, src, mask, width);
|
||||
}
|
||||
|
||||
void
|
||||
_pixman_implementation_combine_64 (pixman_implementation_t * imp,
|
||||
pixman_op_t op,
|
||||
uint64_t * dest,
|
||||
const uint64_t * src,
|
||||
const uint64_t * mask,
|
||||
int width)
|
||||
_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)
|
||||
{
|
||||
(*imp->combine_64[op]) (imp, op, dest, src, mask, width);
|
||||
pixman_implementation_t *imp;
|
||||
cache_t *cache;
|
||||
int i;
|
||||
|
||||
/* Check cache for fast paths */
|
||||
cache = PIXMAN_GET_THREAD_LOCAL (fast_path_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 composite function found\n"
|
||||
"\n"
|
||||
"The most likely cause of this is that this system has issues with\n"
|
||||
"thread local storage\n");
|
||||
|
||||
*out_imp = NULL;
|
||||
*out_func = dummy_composite_rect;
|
||||
return;
|
||||
|
||||
update_cache:
|
||||
if (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;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_pixman_implementation_combine_32_ca (pixman_implementation_t * imp,
|
||||
pixman_op_t op,
|
||||
uint32_t * dest,
|
||||
const uint32_t * src,
|
||||
const uint32_t * mask,
|
||||
int width)
|
||||
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)
|
||||
{
|
||||
(*imp->combine_32_ca[op]) (imp, op, dest, src, mask, width);
|
||||
}
|
||||
|
||||
void
|
||||
_pixman_implementation_combine_64_ca (pixman_implementation_t * imp,
|
||||
pixman_op_t op,
|
||||
uint64_t * dest,
|
||||
const uint64_t * src,
|
||||
const uint64_t * mask,
|
||||
int width)
|
||||
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)
|
||||
{
|
||||
(*imp->combine_64_ca[op]) (imp, op, dest, src, mask, width);
|
||||
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 (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
|
||||
@ -201,14 +239,25 @@ _pixman_implementation_blt (pixman_implementation_t * imp,
|
||||
int dst_bpp,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
int dest_x,
|
||||
int dest_y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
return (*imp->blt) (imp, src_bits, dst_bits, src_stride, dst_stride,
|
||||
src_bpp, dst_bpp, src_x, src_y, dst_x, dst_y,
|
||||
width, 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
|
||||
@ -220,8 +269,130 @@ _pixman_implementation_fill (pixman_implementation_t *imp,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
uint32_t xor)
|
||||
uint32_t filler)
|
||||
{
|
||||
return (*imp->fill) (imp, bits, stride, bpp, x, y, width, height, xor);
|
||||
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_implementation_create_noop (imp);
|
||||
|
||||
return imp;
|
||||
}
|
||||
|
1339
programs/develop/libraries/pixman/pixman-inlines.h
Normal file
1339
programs/develop/libraries/pixman/pixman-inlines.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -31,36 +31,32 @@
|
||||
#include <stdlib.h>
|
||||
#include "pixman-private.h"
|
||||
|
||||
static source_image_class_t
|
||||
linear_gradient_classify (pixman_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
static pixman_bool_t
|
||||
linear_gradient_is_horizontal (pixman_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
source_image_t *source = (source_image_t *)image;
|
||||
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;
|
||||
source_image_class_t class;
|
||||
|
||||
class = SOURCE_IMAGE_CLASS_UNKNOWN;
|
||||
|
||||
if (source->common.transform)
|
||||
if (image->common.transform)
|
||||
{
|
||||
/* projective transformation */
|
||||
if (source->common.transform->matrix[2][0] != 0 ||
|
||||
source->common.transform->matrix[2][1] != 0 ||
|
||||
source->common.transform->matrix[2][2] == 0)
|
||||
if (image->common.transform->matrix[2][0] != 0 ||
|
||||
image->common.transform->matrix[2][1] != 0 ||
|
||||
image->common.transform->matrix[2][2] == 0)
|
||||
{
|
||||
return class;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
v.vector[0] = source->common.transform->matrix[0][1];
|
||||
v.vector[1] = source->common.transform->matrix[1][1];
|
||||
v.vector[2] = source->common.transform->matrix[2][2];
|
||||
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
|
||||
{
|
||||
@ -75,7 +71,7 @@ linear_gradient_classify (pixman_image_t *image,
|
||||
l = dx * dx + dy * dy;
|
||||
|
||||
if (l == 0)
|
||||
return class;
|
||||
return FALSE;
|
||||
|
||||
/*
|
||||
* compute how much the input of the gradient walked changes
|
||||
@ -87,43 +83,44 @@ linear_gradient_classify (pixman_image_t *image,
|
||||
|
||||
/* check that casting to integer would result in 0 */
|
||||
if (-1 < inc && inc < 1)
|
||||
class = SOURCE_IMAGE_CLASS_HORIZONTAL;
|
||||
return TRUE;
|
||||
|
||||
return class;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
linear_gradient_get_scanline_32 (pixman_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
uint32_t * buffer,
|
||||
const uint32_t *mask)
|
||||
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;
|
||||
source_image_t *source = (source_image_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, source->common.repeat);
|
||||
_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 (source->common.transform)
|
||||
if (image->common.transform)
|
||||
{
|
||||
if (!pixman_transform_point_3d (source->common.transform, &v))
|
||||
return;
|
||||
|
||||
unit.vector[0] = source->common.transform->matrix[0][0];
|
||||
unit.vector[1] = source->common.transform->matrix[1][0];
|
||||
unit.vector[2] = source->common.transform->matrix[2][0];
|
||||
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
|
||||
{
|
||||
@ -219,18 +216,48 @@ linear_gradient_get_scanline_32 (pixman_image_t *image,
|
||||
v.vector[2] += unit.vector[2];
|
||||
}
|
||||
}
|
||||
|
||||
iter->y++;
|
||||
|
||||
return iter->buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
linear_gradient_property_changed (pixman_image_t *image)
|
||||
static uint32_t *
|
||||
linear_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
image->common.get_scanline_32 = linear_gradient_get_scanline_32;
|
||||
image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64;
|
||||
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)
|
||||
{
|
||||
if (linear_gradient_is_horizontal (
|
||||
iter->image, iter->x, iter->y, iter->width, iter->height))
|
||||
{
|
||||
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_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 (pixman_point_fixed_t * p1,
|
||||
pixman_point_fixed_t * p2,
|
||||
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)
|
||||
{
|
||||
@ -254,8 +281,6 @@ pixman_image_create_linear_gradient (pixman_point_fixed_t * p1,
|
||||
linear->p2 = *p2;
|
||||
|
||||
image->type = LINEAR;
|
||||
image->common.classify = linear_gradient_classify;
|
||||
image->common.property_changed = linear_gradient_property_changed;
|
||||
|
||||
return image;
|
||||
}
|
||||
|
@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
@ -34,6 +34,338 @@
|
||||
|
||||
#define F(x) pixman_int_to_fixed (x)
|
||||
|
||||
static force_inline int
|
||||
count_leading_zeros (uint32_t x)
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
return __builtin_clz (x);
|
||||
#else
|
||||
int n = 0;
|
||||
while (x)
|
||||
{
|
||||
n++;
|
||||
x >>= 1;
|
||||
}
|
||||
return 32 - n;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Large signed/unsigned integer division with rounding for the platforms with
|
||||
* only 64-bit integer data type supported (no 128-bit data type).
|
||||
*
|
||||
* Arguments:
|
||||
* hi, lo - high and low 64-bit parts of the dividend
|
||||
* div - 48-bit divisor
|
||||
*
|
||||
* Returns: lowest 64 bits of the result as a return value and highest 64
|
||||
* bits of the result to "result_hi" pointer
|
||||
*/
|
||||
|
||||
/* grade-school unsigned division (128-bit by 48-bit) with rounding to nearest */
|
||||
static force_inline uint64_t
|
||||
rounded_udiv_128_by_48 (uint64_t hi,
|
||||
uint64_t lo,
|
||||
uint64_t div,
|
||||
uint64_t *result_hi)
|
||||
{
|
||||
uint64_t tmp, remainder, result_lo;
|
||||
assert(div < ((uint64_t)1 << 48));
|
||||
|
||||
remainder = hi % div;
|
||||
*result_hi = hi / div;
|
||||
|
||||
tmp = (remainder << 16) + (lo >> 48);
|
||||
result_lo = tmp / div;
|
||||
remainder = tmp % div;
|
||||
|
||||
tmp = (remainder << 16) + ((lo >> 32) & 0xFFFF);
|
||||
result_lo = (result_lo << 16) + (tmp / div);
|
||||
remainder = tmp % div;
|
||||
|
||||
tmp = (remainder << 16) + ((lo >> 16) & 0xFFFF);
|
||||
result_lo = (result_lo << 16) + (tmp / div);
|
||||
remainder = tmp % div;
|
||||
|
||||
tmp = (remainder << 16) + (lo & 0xFFFF);
|
||||
result_lo = (result_lo << 16) + (tmp / div);
|
||||
remainder = tmp % div;
|
||||
|
||||
/* round to nearest */
|
||||
if (remainder * 2 >= div && ++result_lo == 0)
|
||||
*result_hi += 1;
|
||||
|
||||
return result_lo;
|
||||
}
|
||||
|
||||
/* signed division (128-bit by 49-bit) with rounding to nearest */
|
||||
static inline int64_t
|
||||
rounded_sdiv_128_by_49 (int64_t hi,
|
||||
uint64_t lo,
|
||||
int64_t div,
|
||||
int64_t *signed_result_hi)
|
||||
{
|
||||
uint64_t result_lo, result_hi;
|
||||
int sign = 0;
|
||||
if (div < 0)
|
||||
{
|
||||
div = -div;
|
||||
sign ^= 1;
|
||||
}
|
||||
if (hi < 0)
|
||||
{
|
||||
if (lo != 0)
|
||||
hi++;
|
||||
hi = -hi;
|
||||
lo = -lo;
|
||||
sign ^= 1;
|
||||
}
|
||||
result_lo = rounded_udiv_128_by_48 (hi, lo, div, &result_hi);
|
||||
if (sign)
|
||||
{
|
||||
if (result_lo != 0)
|
||||
result_hi++;
|
||||
result_hi = -result_hi;
|
||||
result_lo = -result_lo;
|
||||
}
|
||||
if (signed_result_hi)
|
||||
{
|
||||
*signed_result_hi = result_hi;
|
||||
}
|
||||
return result_lo;
|
||||
}
|
||||
|
||||
/*
|
||||
* Multiply 64.16 fixed point value by (2^scalebits) and convert
|
||||
* to 128-bit integer.
|
||||
*/
|
||||
static force_inline void
|
||||
fixed_64_16_to_int128 (int64_t hi,
|
||||
int64_t lo,
|
||||
int64_t *rhi,
|
||||
int64_t *rlo,
|
||||
int scalebits)
|
||||
{
|
||||
/* separate integer and fractional parts */
|
||||
hi += lo >> 16;
|
||||
lo &= 0xFFFF;
|
||||
|
||||
if (scalebits <= 0)
|
||||
{
|
||||
*rlo = hi >> (-scalebits);
|
||||
*rhi = *rlo >> 63;
|
||||
}
|
||||
else
|
||||
{
|
||||
*rhi = hi >> (64 - scalebits);
|
||||
*rlo = (uint64_t)hi << scalebits;
|
||||
if (scalebits < 16)
|
||||
*rlo += lo >> (16 - scalebits);
|
||||
else
|
||||
*rlo += lo << (scalebits - 16);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert 112.16 fixed point value to 48.16 with clamping for the out
|
||||
* of range values.
|
||||
*/
|
||||
static force_inline pixman_fixed_48_16_t
|
||||
fixed_112_16_to_fixed_48_16 (int64_t hi, int64_t lo, pixman_bool_t *clampflag)
|
||||
{
|
||||
if ((lo >> 63) != hi)
|
||||
{
|
||||
*clampflag = TRUE;
|
||||
return hi >= 0 ? INT64_MAX : INT64_MIN;
|
||||
}
|
||||
else
|
||||
{
|
||||
return lo;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Transform a point with 31.16 fixed point coordinates from the destination
|
||||
* space to a point with 48.16 fixed point coordinates in the source space.
|
||||
* No overflows are possible for affine transformations and the results are
|
||||
* accurate including the least significant bit. Projective transformations
|
||||
* may overflow, in this case the results are just clamped to return maximum
|
||||
* or minimum 48.16 values (so that the caller can at least handle the NONE
|
||||
* and PAD repeats correctly) and the return value is FALSE to indicate that
|
||||
* such clamping has happened.
|
||||
*/
|
||||
PIXMAN_EXPORT pixman_bool_t
|
||||
pixman_transform_point_31_16 (const pixman_transform_t *t,
|
||||
const pixman_vector_48_16_t *v,
|
||||
pixman_vector_48_16_t *result)
|
||||
{
|
||||
pixman_bool_t clampflag = FALSE;
|
||||
int i;
|
||||
int64_t tmp[3][2], divint;
|
||||
uint16_t divfrac;
|
||||
|
||||
/* input vector values must have no more than 31 bits (including sign)
|
||||
* in the integer part */
|
||||
assert (v->v[0] < ((pixman_fixed_48_16_t)1 << (30 + 16)));
|
||||
assert (v->v[0] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
|
||||
assert (v->v[1] < ((pixman_fixed_48_16_t)1 << (30 + 16)));
|
||||
assert (v->v[1] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
|
||||
assert (v->v[2] < ((pixman_fixed_48_16_t)1 << (30 + 16)));
|
||||
assert (v->v[2] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
tmp[i][0] = (int64_t)t->matrix[i][0] * (v->v[0] >> 16);
|
||||
tmp[i][1] = (int64_t)t->matrix[i][0] * (v->v[0] & 0xFFFF);
|
||||
tmp[i][0] += (int64_t)t->matrix[i][1] * (v->v[1] >> 16);
|
||||
tmp[i][1] += (int64_t)t->matrix[i][1] * (v->v[1] & 0xFFFF);
|
||||
tmp[i][0] += (int64_t)t->matrix[i][2] * (v->v[2] >> 16);
|
||||
tmp[i][1] += (int64_t)t->matrix[i][2] * (v->v[2] & 0xFFFF);
|
||||
}
|
||||
|
||||
/*
|
||||
* separate 64-bit integer and 16-bit fractional parts for the divisor,
|
||||
* which is also scaled by 65536 after fixed point multiplication.
|
||||
*/
|
||||
divint = tmp[2][0] + (tmp[2][1] >> 16);
|
||||
divfrac = tmp[2][1] & 0xFFFF;
|
||||
|
||||
if (divint == pixman_fixed_1 && divfrac == 0)
|
||||
{
|
||||
/*
|
||||
* this is a simple affine transformation
|
||||
*/
|
||||
result->v[0] = tmp[0][0] + ((tmp[0][1] + 0x8000) >> 16);
|
||||
result->v[1] = tmp[1][0] + ((tmp[1][1] + 0x8000) >> 16);
|
||||
result->v[2] = pixman_fixed_1;
|
||||
}
|
||||
else if (divint == 0 && divfrac == 0)
|
||||
{
|
||||
/*
|
||||
* handle zero divisor (if the values are non-zero, set the
|
||||
* results to maximum positive or minimum negative)
|
||||
*/
|
||||
clampflag = TRUE;
|
||||
|
||||
result->v[0] = tmp[0][0] + ((tmp[0][1] + 0x8000) >> 16);
|
||||
result->v[1] = tmp[1][0] + ((tmp[1][1] + 0x8000) >> 16);
|
||||
|
||||
if (result->v[0] > 0)
|
||||
result->v[0] = INT64_MAX;
|
||||
else if (result->v[0] < 0)
|
||||
result->v[0] = INT64_MIN;
|
||||
|
||||
if (result->v[1] > 0)
|
||||
result->v[1] = INT64_MAX;
|
||||
else if (result->v[1] < 0)
|
||||
result->v[1] = INT64_MIN;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* projective transformation, analyze the top 32 bits of the divisor
|
||||
*/
|
||||
int32_t hi32divbits = divint >> 32;
|
||||
if (hi32divbits < 0)
|
||||
hi32divbits = ~hi32divbits;
|
||||
|
||||
if (hi32divbits == 0)
|
||||
{
|
||||
/* the divisor is small, we can actually keep all the bits */
|
||||
int64_t hi, rhi, lo, rlo;
|
||||
int64_t div = (divint << 16) + divfrac;
|
||||
|
||||
fixed_64_16_to_int128 (tmp[0][0], tmp[0][1], &hi, &lo, 32);
|
||||
rlo = rounded_sdiv_128_by_49 (hi, lo, div, &rhi);
|
||||
result->v[0] = fixed_112_16_to_fixed_48_16 (rhi, rlo, &clampflag);
|
||||
|
||||
fixed_64_16_to_int128 (tmp[1][0], tmp[1][1], &hi, &lo, 32);
|
||||
rlo = rounded_sdiv_128_by_49 (hi, lo, div, &rhi);
|
||||
result->v[1] = fixed_112_16_to_fixed_48_16 (rhi, rlo, &clampflag);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* the divisor needs to be reduced to 48 bits */
|
||||
int64_t hi, rhi, lo, rlo, div;
|
||||
int shift = 32 - count_leading_zeros (hi32divbits);
|
||||
fixed_64_16_to_int128 (divint, divfrac, &hi, &div, 16 - shift);
|
||||
|
||||
fixed_64_16_to_int128 (tmp[0][0], tmp[0][1], &hi, &lo, 32 - shift);
|
||||
rlo = rounded_sdiv_128_by_49 (hi, lo, div, &rhi);
|
||||
result->v[0] = fixed_112_16_to_fixed_48_16 (rhi, rlo, &clampflag);
|
||||
|
||||
fixed_64_16_to_int128 (tmp[1][0], tmp[1][1], &hi, &lo, 32 - shift);
|
||||
rlo = rounded_sdiv_128_by_49 (hi, lo, div, &rhi);
|
||||
result->v[1] = fixed_112_16_to_fixed_48_16 (rhi, rlo, &clampflag);
|
||||
}
|
||||
}
|
||||
result->v[2] = pixman_fixed_1;
|
||||
return !clampflag;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_transform_point_31_16_affine (const pixman_transform_t *t,
|
||||
const pixman_vector_48_16_t *v,
|
||||
pixman_vector_48_16_t *result)
|
||||
{
|
||||
int64_t hi0, lo0, hi1, lo1;
|
||||
|
||||
/* input vector values must have no more than 31 bits (including sign)
|
||||
* in the integer part */
|
||||
assert (v->v[0] < ((pixman_fixed_48_16_t)1 << (30 + 16)));
|
||||
assert (v->v[0] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
|
||||
assert (v->v[1] < ((pixman_fixed_48_16_t)1 << (30 + 16)));
|
||||
assert (v->v[1] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
|
||||
|
||||
hi0 = (int64_t)t->matrix[0][0] * (v->v[0] >> 16);
|
||||
lo0 = (int64_t)t->matrix[0][0] * (v->v[0] & 0xFFFF);
|
||||
hi0 += (int64_t)t->matrix[0][1] * (v->v[1] >> 16);
|
||||
lo0 += (int64_t)t->matrix[0][1] * (v->v[1] & 0xFFFF);
|
||||
hi0 += (int64_t)t->matrix[0][2];
|
||||
|
||||
hi1 = (int64_t)t->matrix[1][0] * (v->v[0] >> 16);
|
||||
lo1 = (int64_t)t->matrix[1][0] * (v->v[0] & 0xFFFF);
|
||||
hi1 += (int64_t)t->matrix[1][1] * (v->v[1] >> 16);
|
||||
lo1 += (int64_t)t->matrix[1][1] * (v->v[1] & 0xFFFF);
|
||||
hi1 += (int64_t)t->matrix[1][2];
|
||||
|
||||
result->v[0] = hi0 + ((lo0 + 0x8000) >> 16);
|
||||
result->v[1] = hi1 + ((lo1 + 0x8000) >> 16);
|
||||
result->v[2] = pixman_fixed_1;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_transform_point_31_16_3d (const pixman_transform_t *t,
|
||||
const pixman_vector_48_16_t *v,
|
||||
pixman_vector_48_16_t *result)
|
||||
{
|
||||
int i;
|
||||
int64_t tmp[3][2];
|
||||
|
||||
/* input vector values must have no more than 31 bits (including sign)
|
||||
* in the integer part */
|
||||
assert (v->v[0] < ((pixman_fixed_48_16_t)1 << (30 + 16)));
|
||||
assert (v->v[0] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
|
||||
assert (v->v[1] < ((pixman_fixed_48_16_t)1 << (30 + 16)));
|
||||
assert (v->v[1] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
|
||||
assert (v->v[2] < ((pixman_fixed_48_16_t)1 << (30 + 16)));
|
||||
assert (v->v[2] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
tmp[i][0] = (int64_t)t->matrix[i][0] * (v->v[0] >> 16);
|
||||
tmp[i][1] = (int64_t)t->matrix[i][0] * (v->v[0] & 0xFFFF);
|
||||
tmp[i][0] += (int64_t)t->matrix[i][1] * (v->v[1] >> 16);
|
||||
tmp[i][1] += (int64_t)t->matrix[i][1] * (v->v[1] & 0xFFFF);
|
||||
tmp[i][0] += (int64_t)t->matrix[i][2] * (v->v[2] >> 16);
|
||||
tmp[i][1] += (int64_t)t->matrix[i][2] * (v->v[2] & 0xFFFF);
|
||||
}
|
||||
|
||||
result->v[0] = tmp[0][0] + ((tmp[0][1] + 0x8000) >> 16);
|
||||
result->v[1] = tmp[1][0] + ((tmp[1][1] + 0x8000) >> 16);
|
||||
result->v[2] = tmp[2][0] + ((tmp[2][1] + 0x8000) >> 16);
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_transform_init_identity (struct pixman_transform *matrix)
|
||||
{
|
||||
@ -50,69 +382,41 @@ PIXMAN_EXPORT pixman_bool_t
|
||||
pixman_transform_point_3d (const struct pixman_transform *transform,
|
||||
struct pixman_vector * vector)
|
||||
{
|
||||
struct pixman_vector result;
|
||||
pixman_fixed_32_32_t partial;
|
||||
pixman_fixed_48_16_t v;
|
||||
int i, j;
|
||||
pixman_vector_48_16_t tmp;
|
||||
tmp.v[0] = vector->vector[0];
|
||||
tmp.v[1] = vector->vector[1];
|
||||
tmp.v[2] = vector->vector[2];
|
||||
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
v = 0;
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
partial = ((pixman_fixed_48_16_t) transform->matrix[j][i] *
|
||||
(pixman_fixed_48_16_t) vector->vector[i]);
|
||||
v += partial >> 16;
|
||||
}
|
||||
|
||||
if (v > pixman_max_fixed_48_16 || v < pixman_min_fixed_48_16)
|
||||
return FALSE;
|
||||
|
||||
result.vector[j] = (pixman_fixed_t) v;
|
||||
}
|
||||
|
||||
*vector = result;
|
||||
pixman_transform_point_31_16_3d (transform, &tmp, &tmp);
|
||||
|
||||
if (!result.vector[2])
|
||||
return FALSE;
|
||||
vector->vector[0] = tmp.v[0];
|
||||
vector->vector[1] = tmp.v[1];
|
||||
vector->vector[2] = tmp.v[2];
|
||||
|
||||
return TRUE;
|
||||
return vector->vector[0] == tmp.v[0] &&
|
||||
vector->vector[1] == tmp.v[1] &&
|
||||
vector->vector[2] == tmp.v[2];
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT pixman_bool_t
|
||||
pixman_transform_point (const struct pixman_transform *transform,
|
||||
struct pixman_vector * vector)
|
||||
{
|
||||
pixman_fixed_32_32_t partial;
|
||||
pixman_fixed_34_30_t v[3];
|
||||
pixman_fixed_48_16_t quo;
|
||||
int i, j;
|
||||
pixman_vector_48_16_t tmp;
|
||||
tmp.v[0] = vector->vector[0];
|
||||
tmp.v[1] = vector->vector[1];
|
||||
tmp.v[2] = vector->vector[2];
|
||||
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
v[j] = 0;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
partial = ((pixman_fixed_32_32_t) transform->matrix[j][i] *
|
||||
(pixman_fixed_32_32_t) vector->vector[i]);
|
||||
v[j] += partial >> 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(v[2] >> 16))
|
||||
return FALSE;
|
||||
if (!pixman_transform_point_31_16 (transform, &tmp, &tmp))
|
||||
return FALSE;
|
||||
|
||||
for (j = 0; j < 2; j++)
|
||||
{
|
||||
quo = v[j] / (v[2] >> 16);
|
||||
if (quo > pixman_max_fixed_48_16 || quo < pixman_min_fixed_48_16)
|
||||
return FALSE;
|
||||
vector->vector[j] = (pixman_fixed_t) quo;
|
||||
}
|
||||
|
||||
vector->vector[2] = pixman_fixed_1;
|
||||
return TRUE;
|
||||
vector->vector[0] = tmp.v[0];
|
||||
vector->vector[1] = tmp.v[1];
|
||||
vector->vector[2] = tmp.v[2];
|
||||
|
||||
return vector->vector[0] == tmp.v[0] &&
|
||||
vector->vector[1] == tmp.v[1] &&
|
||||
vector->vector[2] == tmp.v[2];
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT pixman_bool_t
|
||||
@ -138,7 +442,7 @@ pixman_transform_multiply (struct pixman_transform * dst,
|
||||
(pixman_fixed_32_32_t) l->matrix[dy][o] *
|
||||
(pixman_fixed_32_32_t) r->matrix[o][dx];
|
||||
|
||||
v += partial >> 16;
|
||||
v += (partial + 0x8000) >> 16;
|
||||
}
|
||||
|
||||
if (v > pixman_max_fixed_48_16 || v < pixman_min_fixed_48_16)
|
||||
@ -336,14 +640,14 @@ PIXMAN_EXPORT pixman_bool_t
|
||||
pixman_transform_invert (struct pixman_transform * dst,
|
||||
const struct pixman_transform *src)
|
||||
{
|
||||
struct pixman_f_transform m, r;
|
||||
struct pixman_f_transform m;
|
||||
|
||||
pixman_f_transform_from_pixman_transform (&m, src);
|
||||
|
||||
if (!pixman_f_transform_invert (&r, &m))
|
||||
if (!pixman_f_transform_invert (&m, &m))
|
||||
return FALSE;
|
||||
|
||||
if (!pixman_transform_from_pixman_f_transform (dst, &r))
|
||||
if (!pixman_transform_from_pixman_f_transform (dst, &m))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
@ -425,7 +729,8 @@ pixman_transform_is_inverse (const struct pixman_transform *a,
|
||||
{
|
||||
struct pixman_transform t;
|
||||
|
||||
pixman_transform_multiply (&t, a, b);
|
||||
if (!pixman_transform_multiply (&t, a, b))
|
||||
return FALSE;
|
||||
|
||||
return pixman_transform_is_identity (&t);
|
||||
}
|
||||
@ -464,17 +769,15 @@ pixman_transform_from_pixman_f_transform (struct pixman_transform * t,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const int a[3] = { 3, 3, 2 };
|
||||
static const int b[3] = { 2, 1, 1 };
|
||||
|
||||
PIXMAN_EXPORT pixman_bool_t
|
||||
pixman_f_transform_invert (struct pixman_f_transform * dst,
|
||||
const struct pixman_f_transform *src)
|
||||
{
|
||||
static const int a[3] = { 2, 2, 1 };
|
||||
static const int b[3] = { 1, 0, 0 };
|
||||
pixman_f_transform_t d;
|
||||
double det;
|
||||
int i, j;
|
||||
static int a[3] = { 2, 2, 1 };
|
||||
static int b[3] = { 1, 0, 0 };
|
||||
|
||||
det = 0;
|
||||
for (i = 0; i < 3; i++)
|
||||
@ -509,10 +812,12 @@ pixman_f_transform_invert (struct pixman_f_transform * dst,
|
||||
if (((i + j) & 1) != 0)
|
||||
p = -p;
|
||||
|
||||
dst->m[j][i] = det * p;
|
||||
d.m[j][i] = det * p;
|
||||
}
|
||||
}
|
||||
|
||||
*dst = d;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
176
programs/develop/libraries/pixman/pixman-noop.c
Normal file
176
programs/develop/libraries/pixman/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;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -78,11 +78,11 @@ radial_compute_color (double a,
|
||||
{
|
||||
/*
|
||||
* In this function error propagation can lead to bad results:
|
||||
* - det can have an unbound error (if b*b-a*c is very small),
|
||||
* - 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 sqrtdet;
|
||||
* if det has the wrong sign or b is very small, this can lead to bad
|
||||
* 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
|
||||
@ -92,7 +92,7 @@ radial_compute_color (double a,
|
||||
*
|
||||
* - the above problems are worse if a is small (as inva becomes bigger)
|
||||
*/
|
||||
double det;
|
||||
double discr;
|
||||
|
||||
if (a == 0)
|
||||
{
|
||||
@ -109,22 +109,33 @@ radial_compute_color (double a,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t * dr > mindr)
|
||||
if (t * dr >= mindr)
|
||||
return _pixman_gradient_walker_pixel (walker, t);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
det = fdot (b, a, 0, b, -c, 0);
|
||||
if (det >= 0)
|
||||
discr = fdot (b, a, 0, b, -c, 0);
|
||||
if (discr >= 0)
|
||||
{
|
||||
double sqrtdet, t0, t1;
|
||||
double sqrtdiscr, t0, t1;
|
||||
|
||||
sqrtdet = sqrt (det);
|
||||
t0 = (b + sqrtdet) * inva;
|
||||
t1 = (b - sqrtdet) * inva;
|
||||
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)
|
||||
@ -134,9 +145,9 @@ radial_compute_color (double a,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t0 * dr > mindr)
|
||||
if (t0 * dr >= mindr)
|
||||
return _pixman_gradient_walker_pixel (walker, t0);
|
||||
else if (t1 * dr > mindr)
|
||||
else if (t1 * dr >= mindr)
|
||||
return _pixman_gradient_walker_pixel (walker, t1);
|
||||
}
|
||||
}
|
||||
@ -144,19 +155,14 @@ radial_compute_color (double a,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
radial_gradient_get_scanline_32 (pixman_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
uint32_t * buffer,
|
||||
const uint32_t *mask)
|
||||
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.
|
||||
*
|
||||
@ -173,7 +179,7 @@ radial_gradient_get_scanline_32 (pixman_image_t *image,
|
||||
*
|
||||
* 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 operatior composition.
|
||||
* 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
|
||||
@ -184,14 +190,14 @@ radial_gradient_get_scanline_32 (pixman_image_t *image,
|
||||
* 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₁
|
||||
* lenght(t·cd - pd) = r₁ + t·dr
|
||||
* length(t·cd - pd) = r₁ + t·dr
|
||||
*
|
||||
* which actually means
|
||||
*
|
||||
@ -217,7 +223,7 @@ radial_gradient_get_scanline_32 (pixman_image_t *image,
|
||||
* 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
|
||||
@ -233,9 +239,13 @@ radial_gradient_get_scanline_32 (pixman_image_t *image,
|
||||
* <=> 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;
|
||||
source_image_t *source = (source_image_t *)image;
|
||||
radial_gradient_t *radial = (radial_gradient_t *)image;
|
||||
uint32_t *end = buffer + width;
|
||||
pixman_gradient_walker_t walker;
|
||||
@ -246,16 +256,16 @@ radial_gradient_get_scanline_32 (pixman_image_t *image,
|
||||
v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2;
|
||||
v.vector[2] = pixman_fixed_1;
|
||||
|
||||
_pixman_gradient_walker_init (&walker, gradient, source->common.repeat);
|
||||
_pixman_gradient_walker_init (&walker, gradient, image->common.repeat);
|
||||
|
||||
if (source->common.transform)
|
||||
if (image->common.transform)
|
||||
{
|
||||
if (!pixman_transform_point_3d (source->common.transform, &v))
|
||||
return;
|
||||
|
||||
unit.vector[0] = source->common.transform->matrix[0][0];
|
||||
unit.vector[1] = source->common.transform->matrix[1][0];
|
||||
unit.vector[2] = source->common.transform->matrix[2][0];
|
||||
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
|
||||
{
|
||||
@ -325,7 +335,7 @@ radial_gradient_get_scanline_32 (pixman_image_t *image,
|
||||
radial->delta.radius,
|
||||
radial->mindr,
|
||||
&walker,
|
||||
source->common.repeat);
|
||||
image->common.repeat);
|
||||
}
|
||||
|
||||
b += db;
|
||||
@ -370,14 +380,14 @@ radial_gradient_get_scanline_32 (pixman_image_t *image,
|
||||
radial->delta.radius,
|
||||
radial->mindr,
|
||||
&walker,
|
||||
source->common.repeat);
|
||||
image->common.repeat);
|
||||
}
|
||||
else
|
||||
{
|
||||
*buffer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
++buffer;
|
||||
|
||||
v.vector[0] += unit.vector[0];
|
||||
@ -385,18 +395,34 @@ radial_gradient_get_scanline_32 (pixman_image_t *image,
|
||||
v.vector[2] += unit.vector[2];
|
||||
}
|
||||
}
|
||||
|
||||
iter->y++;
|
||||
return iter->buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
radial_gradient_property_changed (pixman_image_t *image)
|
||||
static uint32_t *
|
||||
radial_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
image->common.get_scanline_32 = radial_gradient_get_scanline_32;
|
||||
image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64;
|
||||
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_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 (pixman_point_fixed_t * inner,
|
||||
pixman_point_fixed_t * outer,
|
||||
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,
|
||||
@ -441,8 +467,5 @@ pixman_image_create_radial_gradient (pixman_point_fixed_t * inner,
|
||||
|
||||
radial->mindr = -1. * pixman_fixed_1 * radial->c1.radius;
|
||||
|
||||
image->common.property_changed = radial_gradient_property_changed;
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,11 @@
|
||||
|
||||
static const box_type_t PREFIX (_empty_box_) = { 0, 0, 0, 0 };
|
||||
static const region_data_type_t PREFIX (_empty_data_) = { 0, 0 };
|
||||
#if defined (__llvm__) && !defined (__clang__)
|
||||
static const volatile region_data_type_t PREFIX (_broken_data_) = { 0, 0 };
|
||||
#else
|
||||
static const region_data_type_t PREFIX (_broken_data_) = { 0, 0 };
|
||||
#endif
|
||||
|
||||
static box_type_t *pixman_region_empty_box =
|
||||
(box_type_t *)&PREFIX (_empty_box_);
|
||||
@ -198,7 +202,7 @@ PIXREGION_SZOF (size_t n)
|
||||
return size + sizeof(region_data_type_t);
|
||||
}
|
||||
|
||||
static void *
|
||||
static region_data_type_t *
|
||||
alloc_data (size_t n)
|
||||
{
|
||||
size_t sz = PIXREGION_SZOF (n);
|
||||
@ -738,8 +742,7 @@ typedef pixman_bool_t (*overlap_proc_ptr) (region_type_t *region,
|
||||
box_type_t * r2,
|
||||
box_type_t * r2_end,
|
||||
int y1,
|
||||
int y2,
|
||||
int * overlap);
|
||||
int y2);
|
||||
|
||||
static pixman_bool_t
|
||||
pixman_op (region_type_t * new_reg, /* Place to store result */
|
||||
@ -750,10 +753,10 @@ pixman_op (region_type_t * new_reg, /* Place to store result
|
||||
int append_non1, /* Append non-overlapping bands
|
||||
* in region 1 ?
|
||||
*/
|
||||
int append_non2, /* Append non-overlapping bands
|
||||
int append_non2 /* Append non-overlapping bands
|
||||
* in region 2 ?
|
||||
*/
|
||||
int * overlap)
|
||||
)
|
||||
{
|
||||
box_type_t *r1; /* Pointer into first region */
|
||||
box_type_t *r2; /* Pointer into 2d region */
|
||||
@ -824,8 +827,7 @@ pixman_op (region_type_t * new_reg, /* Place to store result
|
||||
{
|
||||
if (!pixman_rect_alloc (new_reg, new_size))
|
||||
{
|
||||
if (old_data)
|
||||
free (old_data);
|
||||
free (old_data);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@ -932,8 +934,7 @@ pixman_op (region_type_t * new_reg, /* Place to store result
|
||||
if (!(*overlap_func)(new_reg,
|
||||
r1, r1_band_end,
|
||||
r2, r2_band_end,
|
||||
ytop, ybot,
|
||||
overlap))
|
||||
ytop, ybot))
|
||||
{
|
||||
goto bail;
|
||||
}
|
||||
@ -1001,8 +1002,7 @@ pixman_op (region_type_t * new_reg, /* Place to store result
|
||||
APPEND_REGIONS (new_reg, r2_band_end, r2_end);
|
||||
}
|
||||
|
||||
if (old_data)
|
||||
free (old_data);
|
||||
free (old_data);
|
||||
|
||||
if (!(numRects = new_reg->data->numRects))
|
||||
{
|
||||
@ -1023,8 +1023,7 @@ pixman_op (region_type_t * new_reg, /* Place to store result
|
||||
return TRUE;
|
||||
|
||||
bail:
|
||||
if (old_data)
|
||||
free (old_data);
|
||||
free (old_data);
|
||||
|
||||
return pixman_break (new_reg);
|
||||
}
|
||||
@ -1112,8 +1111,7 @@ pixman_region_intersect_o (region_type_t *region,
|
||||
box_type_t * r2,
|
||||
box_type_t * r2_end,
|
||||
int y1,
|
||||
int y2,
|
||||
int * overlap)
|
||||
int y2)
|
||||
{
|
||||
int x1;
|
||||
int x2;
|
||||
@ -1209,13 +1207,9 @@ PREFIX (_intersect) (region_type_t * new_reg,
|
||||
else
|
||||
{
|
||||
/* General purpose intersection */
|
||||
int overlap; /* result ignored */
|
||||
|
||||
if (!pixman_op (new_reg, reg1, reg2, pixman_region_intersect_o, FALSE, FALSE,
|
||||
&overlap))
|
||||
{
|
||||
if (!pixman_op (new_reg, reg1, reg2, pixman_region_intersect_o, FALSE, FALSE))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pixman_set_extents (new_reg);
|
||||
}
|
||||
@ -1230,9 +1224,6 @@ PREFIX (_intersect) (region_type_t * new_reg,
|
||||
if (r->x1 <= x2) \
|
||||
{ \
|
||||
/* Merge with current rectangle */ \
|
||||
if (r->x1 < x2) \
|
||||
*overlap = TRUE; \
|
||||
\
|
||||
if (x2 < r->x2) \
|
||||
x2 = r->x2; \
|
||||
} \
|
||||
@ -1272,8 +1263,7 @@ pixman_region_union_o (region_type_t *region,
|
||||
box_type_t * r2,
|
||||
box_type_t * r2_end,
|
||||
int y1,
|
||||
int y2,
|
||||
int * overlap)
|
||||
int y2)
|
||||
{
|
||||
box_type_t *next_rect;
|
||||
int x1; /* left and right side of current union */
|
||||
@ -1382,8 +1372,6 @@ PREFIX (_union) (region_type_t *new_reg,
|
||||
region_type_t *reg1,
|
||||
region_type_t *reg2)
|
||||
{
|
||||
int overlap; /* result ignored */
|
||||
|
||||
/* Return TRUE if some overlap
|
||||
* between reg1, reg2
|
||||
*/
|
||||
@ -1449,7 +1437,7 @@ PREFIX (_union) (region_type_t *new_reg,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!pixman_op (new_reg, reg1, reg2, pixman_region_union_o, TRUE, TRUE, &overlap))
|
||||
if (!pixman_op (new_reg, reg1, reg2, pixman_region_union_o, TRUE, TRUE))
|
||||
return FALSE;
|
||||
|
||||
new_reg->extents.x1 = MIN (reg1->extents.x1, reg2->extents.x1);
|
||||
@ -1516,9 +1504,7 @@ quick_sort_rects (
|
||||
r++;
|
||||
i++;
|
||||
}
|
||||
|
||||
while (i != numRects && (r->y1 < y1 || (r->y1 == y1 && r->x1 < x1)))
|
||||
;
|
||||
while (i != numRects && (r->y1 < y1 || (r->y1 == y1 && r->x1 < x1)));
|
||||
|
||||
r = &(rects[j]);
|
||||
do
|
||||
@ -1579,8 +1565,7 @@ quick_sort_rects (
|
||||
*/
|
||||
|
||||
static pixman_bool_t
|
||||
validate (region_type_t * badreg,
|
||||
int * overlap)
|
||||
validate (region_type_t * badreg)
|
||||
{
|
||||
/* Descriptor for regions under construction in Step 2. */
|
||||
typedef struct
|
||||
@ -1605,7 +1590,6 @@ validate (region_type_t * badreg,
|
||||
region_type_t *hreg; /* ri[j_half].reg */
|
||||
pixman_bool_t ret = TRUE;
|
||||
|
||||
*overlap = FALSE;
|
||||
if (!badreg->data)
|
||||
{
|
||||
GOOD (badreg);
|
||||
@ -1679,9 +1663,6 @@ validate (region_type_t * badreg,
|
||||
if (box->x1 <= ri_box->x2)
|
||||
{
|
||||
/* Merge it with ri_box */
|
||||
if (box->x1 < ri_box->x2)
|
||||
*overlap = TRUE;
|
||||
|
||||
if (box->x2 > ri_box->x2)
|
||||
ri_box->x2 = box->x2;
|
||||
}
|
||||
@ -1785,7 +1766,7 @@ validate (region_type_t * badreg,
|
||||
reg = &ri[j].reg;
|
||||
hreg = &ri[j + half].reg;
|
||||
|
||||
if (!pixman_op (reg, reg, hreg, pixman_region_union_o, TRUE, TRUE, overlap))
|
||||
if (!pixman_op (reg, reg, hreg, pixman_region_union_o, TRUE, TRUE))
|
||||
ret = FALSE;
|
||||
|
||||
if (hreg->extents.x1 < reg->extents.x1)
|
||||
@ -1853,8 +1834,7 @@ pixman_region_subtract_o (region_type_t * region,
|
||||
box_type_t * r2,
|
||||
box_type_t * r2_end,
|
||||
int y1,
|
||||
int y2,
|
||||
int * overlap)
|
||||
int y2)
|
||||
{
|
||||
box_type_t * next_rect;
|
||||
int x1;
|
||||
@ -1878,7 +1858,7 @@ pixman_region_subtract_o (region_type_t * region,
|
||||
else if (r2->x1 <= x1)
|
||||
{
|
||||
/*
|
||||
* Subtrahend preceeds minuend: nuke left edge of minuend.
|
||||
* Subtrahend precedes minuend: nuke left edge of minuend.
|
||||
*/
|
||||
x1 = r2->x2;
|
||||
if (x1 >= r1->x2)
|
||||
@ -1978,8 +1958,6 @@ PREFIX (_subtract) (region_type_t *reg_d,
|
||||
region_type_t *reg_m,
|
||||
region_type_t *reg_s)
|
||||
{
|
||||
int overlap; /* result ignored */
|
||||
|
||||
GOOD (reg_m);
|
||||
GOOD (reg_s);
|
||||
GOOD (reg_d);
|
||||
@ -2004,9 +1982,9 @@ PREFIX (_subtract) (region_type_t *reg_d,
|
||||
}
|
||||
|
||||
/* Add those rectangles in region 1 that aren't in region 2,
|
||||
do yucky substraction for overlaps, and
|
||||
do yucky subtraction for overlaps, and
|
||||
just throw away rectangles in region 2 that aren't in region 1 */
|
||||
if (!pixman_op (reg_d, reg_m, reg_s, pixman_region_subtract_o, TRUE, FALSE, &overlap))
|
||||
if (!pixman_op (reg_d, reg_m, reg_s, pixman_region_subtract_o, TRUE, FALSE))
|
||||
return FALSE;
|
||||
|
||||
/*
|
||||
@ -2040,15 +2018,13 @@ PREFIX (_subtract) (region_type_t *reg_d,
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
pixman_bool_t
|
||||
PIXMAN_EXPORT PREFIX (_inverse) (region_type_t *new_reg, /* Destination region */
|
||||
region_type_t *reg1, /* Region to invert */
|
||||
box_type_t * inv_rect) /* Bounding box for inversion */
|
||||
PIXMAN_EXPORT pixman_bool_t
|
||||
PREFIX (_inverse) (region_type_t *new_reg, /* Destination region */
|
||||
region_type_t *reg1, /* Region to invert */
|
||||
box_type_t * inv_rect) /* Bounding box for inversion */
|
||||
{
|
||||
region_type_t inv_reg; /* Quick and dirty region made from the
|
||||
* bounding box */
|
||||
int overlap; /* result ignored */
|
||||
|
||||
GOOD (reg1);
|
||||
GOOD (new_reg);
|
||||
|
||||
@ -2066,12 +2042,12 @@ PIXMAN_EXPORT PREFIX (_inverse) (region_type_t *new_reg, /* Destination region
|
||||
}
|
||||
|
||||
/* Add those rectangles in region 1 that aren't in region 2,
|
||||
* do yucky substraction for overlaps, and
|
||||
* do yucky subtraction for overlaps, and
|
||||
* just throw away rectangles in region 2 that aren't in region 1
|
||||
*/
|
||||
inv_reg.extents = *inv_rect;
|
||||
inv_reg.data = (region_data_type_t *)NULL;
|
||||
if (!pixman_op (new_reg, &inv_reg, reg1, pixman_region_subtract_o, TRUE, FALSE, &overlap))
|
||||
if (!pixman_op (new_reg, &inv_reg, reg1, pixman_region_subtract_o, TRUE, FALSE))
|
||||
return FALSE;
|
||||
|
||||
/*
|
||||
@ -2086,6 +2062,40 @@ PIXMAN_EXPORT PREFIX (_inverse) (region_type_t *new_reg, /* Destination region
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* In time O(log n), locate the first box whose y2 is greater than y.
|
||||
* Return @end if no such box exists.
|
||||
*/
|
||||
static box_type_t *
|
||||
find_box_for_y (box_type_t *begin, box_type_t *end, int y)
|
||||
{
|
||||
box_type_t *mid;
|
||||
|
||||
if (end == begin)
|
||||
return end;
|
||||
|
||||
if (end - begin == 1)
|
||||
{
|
||||
if (begin->y2 > y)
|
||||
return begin;
|
||||
else
|
||||
return end;
|
||||
}
|
||||
|
||||
mid = begin + (end - begin) / 2;
|
||||
if (mid->y2 > y)
|
||||
{
|
||||
/* If no box is found in [begin, mid], the function
|
||||
* will return @mid, which is then known to be the
|
||||
* correct answer.
|
||||
*/
|
||||
return find_box_for_y (begin, mid, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
return find_box_for_y (mid, end, y);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* rect_in(region, rect)
|
||||
* This routine takes a pointer to a region and a pointer to a box
|
||||
@ -2102,10 +2112,9 @@ PIXMAN_EXPORT PREFIX (_inverse) (region_type_t *new_reg, /* Destination region
|
||||
* partially in the region) or is outside the region (we reached a band
|
||||
* that doesn't overlap the box at all and part_in is false)
|
||||
*/
|
||||
|
||||
pixman_region_overlap_t
|
||||
PIXMAN_EXPORT PREFIX (_contains_rectangle) (region_type_t * region,
|
||||
box_type_t * prect)
|
||||
PIXMAN_EXPORT pixman_region_overlap_t
|
||||
PREFIX (_contains_rectangle) (region_type_t * region,
|
||||
box_type_t * prect)
|
||||
{
|
||||
box_type_t * pbox;
|
||||
box_type_t * pbox_end;
|
||||
@ -2139,12 +2148,15 @@ PIXMAN_EXPORT PREFIX (_contains_rectangle) (region_type_t * region,
|
||||
|
||||
/* can stop when both part_out and part_in are TRUE, or we reach prect->y2 */
|
||||
for (pbox = PIXREGION_BOXPTR (region), pbox_end = pbox + numRects;
|
||||
pbox != pbox_end;
|
||||
pbox++)
|
||||
pbox != pbox_end;
|
||||
pbox++)
|
||||
{
|
||||
|
||||
if (pbox->y2 <= y)
|
||||
continue; /* getting up to speed or skipping remainder of band */
|
||||
/* getting up to speed or skipping remainder of band */
|
||||
if (pbox->y2 <= y)
|
||||
{
|
||||
if ((pbox = find_box_for_y (pbox, pbox_end, y)) == pbox_end)
|
||||
break;
|
||||
}
|
||||
|
||||
if (pbox->y1 > y)
|
||||
{
|
||||
@ -2319,6 +2331,16 @@ PREFIX (_reset) (region_type_t *region, box_type_t *box)
|
||||
region->data = NULL;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
PREFIX (_clear) (region_type_t *region)
|
||||
{
|
||||
GOOD (region);
|
||||
FREE_DATA (region);
|
||||
|
||||
region->extents = *pixman_region_empty_box;
|
||||
region->data = pixman_region_empty_data;
|
||||
}
|
||||
|
||||
/* box is "return" value */
|
||||
PIXMAN_EXPORT int
|
||||
PREFIX (_contains_point) (region_type_t * region,
|
||||
@ -2342,13 +2364,13 @@ PREFIX (_contains_point) (region_type_t * region,
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
for (pbox = PIXREGION_BOXPTR (region), pbox_end = pbox + numRects;
|
||||
pbox != pbox_end;
|
||||
pbox++)
|
||||
{
|
||||
if (y >= pbox->y2)
|
||||
continue; /* not there yet */
|
||||
pbox = PIXREGION_BOXPTR (region);
|
||||
pbox_end = pbox + numRects;
|
||||
|
||||
pbox = find_box_for_y (pbox, pbox_end, y);
|
||||
|
||||
for (;pbox != pbox_end; pbox++)
|
||||
{
|
||||
if ((y < pbox->y1) || (x < pbox->x1))
|
||||
break; /* missed it */
|
||||
|
||||
@ -2528,7 +2550,7 @@ PREFIX (_init_rects) (region_type_t *region,
|
||||
/* Validate */
|
||||
region->extents.x1 = region->extents.x2 = 0;
|
||||
|
||||
return validate (region, &i);
|
||||
return validate (region);
|
||||
}
|
||||
|
||||
#define READ(_ptr) (*(_ptr))
|
||||
@ -2545,8 +2567,7 @@ bitmap_addrect (region_type_t *reg,
|
||||
((r-1)->y1 == ry1) && ((r-1)->y2 == ry2) &&
|
||||
((r-1)->x1 <= rx1) && ((r-1)->x2 >= rx2))))
|
||||
{
|
||||
if (!reg->data ||
|
||||
reg->data->numRects == reg->data->size)
|
||||
if (reg->data->numRects == reg->data->size)
|
||||
{
|
||||
if (!pixman_rect_alloc (reg, 1))
|
||||
return NULL;
|
||||
@ -2590,6 +2611,8 @@ PREFIX (_init_from_image) (region_type_t *region,
|
||||
|
||||
PREFIX(_init) (region);
|
||||
|
||||
critical_if_fail (region->data);
|
||||
|
||||
return_if_fail (image->type == BITS);
|
||||
return_if_fail (image->bits.format == PIXMAN_a1);
|
||||
|
||||
|
@ -26,56 +26,6 @@
|
||||
#endif
|
||||
#include "pixman-private.h"
|
||||
|
||||
static void
|
||||
solid_fill_get_scanline_32 (pixman_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
uint32_t * buffer,
|
||||
const uint32_t *mask)
|
||||
{
|
||||
uint32_t *end = buffer + width;
|
||||
uint32_t color = image->solid.color_32;
|
||||
|
||||
while (buffer < end)
|
||||
*(buffer++) = color;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
solid_fill_get_scanline_64 (pixman_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
uint32_t * buffer,
|
||||
const uint32_t *mask)
|
||||
{
|
||||
uint64_t *b = (uint64_t *)buffer;
|
||||
uint64_t *e = b + width;
|
||||
uint64_t color = image->solid.color_64;
|
||||
|
||||
while (b < e)
|
||||
*(b++) = color;
|
||||
}
|
||||
|
||||
static source_image_class_t
|
||||
solid_fill_classify (pixman_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
return SOURCE_IMAGE_CLASS_HORIZONTAL;
|
||||
}
|
||||
|
||||
static void
|
||||
solid_fill_property_changed (pixman_image_t *image)
|
||||
{
|
||||
image->common.get_scanline_32 = solid_fill_get_scanline_32;
|
||||
image->common.get_scanline_64 = solid_fill_get_scanline_64;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
color_to_uint32 (const pixman_color_t *color)
|
||||
{
|
||||
@ -86,18 +36,21 @@ color_to_uint32 (const pixman_color_t *color)
|
||||
(color->blue >> 8);
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
color_to_uint64 (const pixman_color_t *color)
|
||||
static argb_t
|
||||
color_to_float (const pixman_color_t *color)
|
||||
{
|
||||
return
|
||||
((uint64_t)color->alpha << 48) |
|
||||
((uint64_t)color->red << 32) |
|
||||
((uint64_t)color->green << 16) |
|
||||
((uint64_t)color->blue);
|
||||
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 (pixman_color_t *color)
|
||||
pixman_image_create_solid_fill (const pixman_color_t *color)
|
||||
{
|
||||
pixman_image_t *img = _pixman_image_allocate ();
|
||||
|
||||
@ -107,10 +60,7 @@ pixman_image_create_solid_fill (pixman_color_t *color)
|
||||
img->type = SOLID;
|
||||
img->solid.color = *color;
|
||||
img->solid.color_32 = color_to_uint32 (color);
|
||||
img->solid.color_64 = color_to_uint64 (color);
|
||||
|
||||
img->common.classify = solid_fill_classify;
|
||||
img->common.property_changed = solid_fill_property_changed;
|
||||
img->solid.color_float = color_to_float (color);
|
||||
|
||||
return img;
|
||||
}
|
||||
|
6449
programs/develop/libraries/pixman/pixman-sse2.c
Normal file
6449
programs/develop/libraries/pixman/pixman-sse2.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* 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
|
||||
@ -25,6 +26,7 @@
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "pixman-private.h"
|
||||
|
||||
/*
|
||||
@ -137,7 +139,7 @@ _pixman_edge_multi_init (pixman_edge_t * e,
|
||||
if (ne > 0)
|
||||
{
|
||||
int nx = ne / e->dy;
|
||||
ne -= nx * e->dy;
|
||||
ne -= nx * (pixman_fixed_48_16_t)e->dy;
|
||||
stepx += nx * e->signdx;
|
||||
}
|
||||
|
||||
@ -228,14 +230,13 @@ pixman_line_fixed_edge_init (pixman_edge_t * e,
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_add_traps (pixman_image_t * image,
|
||||
int16_t x_off,
|
||||
int16_t y_off,
|
||||
int ntrap,
|
||||
pixman_trap_t * traps)
|
||||
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 width;
|
||||
int height;
|
||||
|
||||
pixman_fixed_t x_off_fixed;
|
||||
@ -245,7 +246,6 @@ pixman_add_traps (pixman_image_t * image,
|
||||
|
||||
_pixman_image_validate (image);
|
||||
|
||||
width = image->bits.width;
|
||||
height = image->bits.height;
|
||||
bpp = PIXMAN_FORMAT_BPP (image->bits.format);
|
||||
|
||||
@ -349,10 +349,8 @@ pixman_rasterize_trapezoid (pixman_image_t * image,
|
||||
int y_off)
|
||||
{
|
||||
int bpp;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
pixman_fixed_t x_off_fixed;
|
||||
pixman_fixed_t y_off_fixed;
|
||||
pixman_edge_t l, r;
|
||||
pixman_fixed_t t, b;
|
||||
@ -364,11 +362,9 @@ pixman_rasterize_trapezoid (pixman_image_t * image,
|
||||
if (!pixman_trapezoid_valid (trap))
|
||||
return;
|
||||
|
||||
width = image->bits.width;
|
||||
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);
|
||||
|
||||
t = trap->top + y_off_fixed;
|
||||
@ -390,3 +386,326 @@ pixman_rasterize_trapezoid (pixman_image_t * image,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -31,15 +31,19 @@
|
||||
#include "pixman-private.h"
|
||||
|
||||
pixman_bool_t
|
||||
pixman_multiply_overflows_int (unsigned int a,
|
||||
unsigned int b)
|
||||
_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)
|
||||
_pixman_addition_overflows_int (unsigned int a, unsigned int b)
|
||||
{
|
||||
return a > INT32_MAX - b;
|
||||
}
|
||||
@ -67,61 +71,96 @@ pixman_malloc_abc (unsigned int a,
|
||||
return malloc (a * b * c);
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper routine to expand a color component from 0 < n <= 8 bits to 16
|
||||
* bits by replication.
|
||||
*/
|
||||
static inline uint64_t
|
||||
expand16 (const uint8_t val, int nbits)
|
||||
static force_inline uint16_t
|
||||
float_to_unorm (float f, int n_bits)
|
||||
{
|
||||
/* Start out with the high bit of val in the high bit of result. */
|
||||
uint16_t result = (uint16_t)val << (16 - nbits);
|
||||
uint32_t u;
|
||||
|
||||
if (nbits == 0)
|
||||
return 0;
|
||||
if (f > 1.0)
|
||||
f = 1.0;
|
||||
if (f < 0.0)
|
||||
f = 0.0;
|
||||
|
||||
/* Copy the bits in result, doubling the number of bits each time, until
|
||||
* we fill all 16 bits.
|
||||
*/
|
||||
while (nbits < 16)
|
||||
{
|
||||
result |= result >> nbits;
|
||||
nbits *= 2;
|
||||
}
|
||||
u = f * (1 << n_bits);
|
||||
u -= (u >> n_bits);
|
||||
|
||||
return result;
|
||||
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 ARGB8 format to ARGB16. To preserve
|
||||
* precision, it needs to know the original source format. For example, if the
|
||||
* source was PIXMAN_x1r5g5b5 and the red component contained bits 12345, then
|
||||
* the expanded value is 12345123. To correctly expand this to 16 bits, it
|
||||
* should be 1234512345123451 and not 1234512312345123.
|
||||
* 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 (uint64_t * dst,
|
||||
const uint32_t * src,
|
||||
pixman_format_code_t format,
|
||||
int width)
|
||||
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.
|
||||
*/
|
||||
const int a_size = PIXMAN_FORMAT_A (format),
|
||||
r_size = PIXMAN_FORMAT_R (format),
|
||||
g_size = PIXMAN_FORMAT_G (format),
|
||||
b_size = PIXMAN_FORMAT_B (format);
|
||||
const int a_shift = 32 - a_size,
|
||||
r_shift = 24 - r_size,
|
||||
g_shift = 16 - g_size,
|
||||
b_shift = 8 - b_size;
|
||||
const uint8_t a_mask = ~(~0 << a_size),
|
||||
r_mask = ~(~0 << r_size),
|
||||
g_mask = ~(~0 << g_size),
|
||||
b_mask = ~(~0 << b_size);
|
||||
int i;
|
||||
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
|
||||
@ -129,44 +168,52 @@ pixman_expand (uint64_t * dst,
|
||||
for (i = width - 1; i >= 0; i--)
|
||||
{
|
||||
const uint32_t pixel = src[i];
|
||||
const uint8_t a = (pixel >> a_shift) & a_mask,
|
||||
r = (pixel >> r_shift) & r_mask,
|
||||
g = (pixel >> g_shift) & g_mask,
|
||||
b = (pixel >> b_shift) & b_mask;
|
||||
const uint64_t a16 = a_size ? expand16 (a, a_size) : 0xffff,
|
||||
r16 = expand16 (r, r_size),
|
||||
g16 = expand16 (g, g_size),
|
||||
b16 = expand16 (b, b_size);
|
||||
|
||||
dst[i] = a16 << 48 | r16 << 32 | g16 << 16 | b16;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Contracting is easier than expanding. We just need to truncate the
|
||||
* components.
|
||||
*/
|
||||
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 (uint32_t * dst,
|
||||
const uint64_t *src,
|
||||
int width)
|
||||
pixman_contract_from_float (uint32_t *dst,
|
||||
const argb_t *src,
|
||||
int width)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Start at the beginning so that we can do the contraction in
|
||||
* place when src == dst
|
||||
*/
|
||||
for (i = 0; i < width; i++)
|
||||
for (i = 0; i < width; ++i)
|
||||
{
|
||||
const uint8_t a = src[i] >> 56,
|
||||
r = src[i] >> 40,
|
||||
g = src[i] >> 24,
|
||||
b = src[i] >> 8;
|
||||
uint8_t a, r, g, b;
|
||||
|
||||
dst[i] = a << 24 | r << 16 | g << 8 | 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
|
||||
@ -236,7 +283,14 @@ pixman_region32_copy_from_region16 (pixman_region32_t *dst,
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/* 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 ();
|
||||
}
|
||||
|
||||
void
|
||||
_pixman_log_error (const char *function, const char *message)
|
||||
@ -254,5 +308,3 @@ _pixman_log_error (const char *function, const char *message)
|
||||
n_messages++;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -32,10 +32,10 @@
|
||||
#endif
|
||||
|
||||
#define PIXMAN_VERSION_MAJOR 0
|
||||
#define PIXMAN_VERSION_MINOR 20
|
||||
#define PIXMAN_VERSION_MINOR 30
|
||||
#define PIXMAN_VERSION_MICRO 2
|
||||
|
||||
#define PIXMAN_VERSION_STRING "0.20.2"
|
||||
#define PIXMAN_VERSION_STRING "0.30.2"
|
||||
|
||||
#define PIXMAN_VERSION_ENCODE(major, minor, micro) ( \
|
||||
((major) * 10000) \
|
||||
|
@ -1,263 +0,0 @@
|
||||
#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 */
|
237
programs/develop/libraries/pixman/pixman-x86.c
Normal file
237
programs/develop/libraries/pixman/pixman-x86.c
Normal file
@ -0,0 +1,237 @@
|
||||
/*
|
||||
* 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
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
@ -30,16 +30,15 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
static force_inline pixman_implementation_t *
|
||||
get_implementation (void)
|
||||
pixman_implementation_t *global_implementation;
|
||||
|
||||
#ifdef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR
|
||||
static void __attribute__((constructor))
|
||||
pixman_constructor (void)
|
||||
{
|
||||
static pixman_implementation_t *global_implementation;
|
||||
|
||||
if (!global_implementation)
|
||||
global_implementation = _pixman_choose_implementation ();
|
||||
|
||||
return global_implementation;
|
||||
global_implementation = _pixman_choose_implementation ();
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef struct operator_info_t operator_info_t;
|
||||
|
||||
@ -153,57 +152,6 @@ optimize_operator (pixman_op_t op,
|
||||
return operator_table[op].opaque_info[is_dest_opaque | is_source_opaque];
|
||||
}
|
||||
|
||||
static void
|
||||
apply_workaround (pixman_image_t *image,
|
||||
int32_t * x,
|
||||
int32_t * y,
|
||||
uint32_t ** save_bits,
|
||||
int * save_dx,
|
||||
int * save_dy)
|
||||
{
|
||||
if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND))
|
||||
{
|
||||
/* Some X servers generate images that point to the
|
||||
* wrong place in memory, but then set the clip region
|
||||
* to point to the right place. Because of an old bug
|
||||
* in pixman, this would actually work.
|
||||
*
|
||||
* Here we try and undo the damage
|
||||
*/
|
||||
int bpp = PIXMAN_FORMAT_BPP (image->bits.format) / 8;
|
||||
pixman_box32_t *extents;
|
||||
uint8_t *t;
|
||||
int dx, dy;
|
||||
|
||||
extents = pixman_region32_extents (&(image->common.clip_region));
|
||||
dx = extents->x1;
|
||||
dy = extents->y1;
|
||||
|
||||
*save_bits = image->bits.bits;
|
||||
|
||||
*x -= dx;
|
||||
*y -= dy;
|
||||
pixman_region32_translate (&(image->common.clip_region), -dx, -dy);
|
||||
|
||||
t = (uint8_t *)image->bits.bits;
|
||||
t += dy * image->bits.rowstride * 4 + dx * bpp;
|
||||
image->bits.bits = (uint32_t *)t;
|
||||
|
||||
*save_dx = dx;
|
||||
*save_dy = dy;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
unapply_workaround (pixman_image_t *image, uint32_t *bits, int dx, int dy)
|
||||
{
|
||||
if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND))
|
||||
{
|
||||
image->bits.bits = bits;
|
||||
pixman_region32_translate (&image->common.clip_region, dx, dy);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Computing composite region
|
||||
*/
|
||||
@ -276,19 +224,19 @@ clip_source_image (pixman_region32_t * region,
|
||||
* returns FALSE if the final region is empty. Indistinguishable from
|
||||
* an allocation failure, but rendering ignores those anyways.
|
||||
*/
|
||||
static pixman_bool_t
|
||||
pixman_compute_composite_region32 (pixman_region32_t * region,
|
||||
pixman_image_t * src_image,
|
||||
pixman_image_t * mask_image,
|
||||
pixman_image_t * dst_image,
|
||||
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_bool_t
|
||||
_pixman_compute_composite_region32 (pixman_region32_t * region,
|
||||
pixman_image_t * src_image,
|
||||
pixman_image_t * mask_image,
|
||||
pixman_image_t * dest_image,
|
||||
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)
|
||||
{
|
||||
region->extents.x1 = dest_x;
|
||||
region->extents.x2 = dest_x + width;
|
||||
@ -297,8 +245,8 @@ pixman_compute_composite_region32 (pixman_region32_t * region,
|
||||
|
||||
region->extents.x1 = MAX (region->extents.x1, 0);
|
||||
region->extents.y1 = MAX (region->extents.y1, 0);
|
||||
region->extents.x2 = MIN (region->extents.x2, dst_image->bits.width);
|
||||
region->extents.y2 = MIN (region->extents.y2, dst_image->bits.height);
|
||||
region->extents.x2 = MIN (region->extents.x2, dest_image->bits.width);
|
||||
region->extents.y2 = MIN (region->extents.y2, dest_image->bits.height);
|
||||
|
||||
region->data = 0;
|
||||
|
||||
@ -313,29 +261,29 @@ pixman_compute_composite_region32 (pixman_region32_t * region,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (dst_image->common.have_clip_region)
|
||||
if (dest_image->common.have_clip_region)
|
||||
{
|
||||
if (!clip_general_image (region, &dst_image->common.clip_region, 0, 0))
|
||||
if (!clip_general_image (region, &dest_image->common.clip_region, 0, 0))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (dst_image->common.alpha_map)
|
||||
if (dest_image->common.alpha_map)
|
||||
{
|
||||
if (!pixman_region32_intersect_rect (region, region,
|
||||
dst_image->common.alpha_origin_x,
|
||||
dst_image->common.alpha_origin_y,
|
||||
dst_image->common.alpha_map->width,
|
||||
dst_image->common.alpha_map->height))
|
||||
dest_image->common.alpha_origin_x,
|
||||
dest_image->common.alpha_origin_y,
|
||||
dest_image->common.alpha_map->width,
|
||||
dest_image->common.alpha_map->height))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (!pixman_region32_not_empty (region))
|
||||
return FALSE;
|
||||
if (dst_image->common.alpha_map->common.have_clip_region)
|
||||
if (dest_image->common.alpha_map->common.have_clip_region)
|
||||
{
|
||||
if (!clip_general_image (region, &dst_image->common.alpha_map->common.clip_region,
|
||||
-dst_image->common.alpha_origin_x,
|
||||
-dst_image->common.alpha_origin_y))
|
||||
if (!clip_general_image (region, &dest_image->common.alpha_map->common.clip_region,
|
||||
-dest_image->common.alpha_origin_x,
|
||||
-dest_image->common.alpha_origin_y))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@ -377,220 +325,89 @@ pixman_compute_composite_region32 (pixman_region32_t * region,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#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_fixed_48_16_t x1;
|
||||
pixman_fixed_48_16_t y1;
|
||||
pixman_fixed_48_16_t x2;
|
||||
pixman_fixed_48_16_t y2;
|
||||
} box_48_16_t;
|
||||
|
||||
PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache);
|
||||
|
||||
static force_inline pixman_bool_t
|
||||
lookup_composite_function (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)
|
||||
static pixman_bool_t
|
||||
compute_transformed_extents (pixman_transform_t *transform,
|
||||
const pixman_box32_t *extents,
|
||||
box_48_16_t *transformed)
|
||||
{
|
||||
pixman_implementation_t *imp;
|
||||
cache_t *cache;
|
||||
pixman_fixed_48_16_t tx1, ty1, tx2, ty2;
|
||||
pixman_fixed_t x1, y1, x2, y2;
|
||||
int i;
|
||||
|
||||
/* Check cache for fast paths */
|
||||
cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache);
|
||||
x1 = pixman_int_to_fixed (extents->x1) + pixman_fixed_1 / 2;
|
||||
y1 = pixman_int_to_fixed (extents->y1) + pixman_fixed_1 / 2;
|
||||
x2 = pixman_int_to_fixed (extents->x2) - pixman_fixed_1 / 2;
|
||||
y2 = pixman_int_to_fixed (extents->y2) - pixman_fixed_1 / 2;
|
||||
|
||||
for (i = 0; i < N_CACHED_FAST_PATHS; ++i)
|
||||
if (!transform)
|
||||
{
|
||||
const pixman_fast_path_t *info = &(cache->cache[i].fast_path);
|
||||
transformed->x1 = x1;
|
||||
transformed->y1 = y1;
|
||||
transformed->x2 = x2;
|
||||
transformed->y2 = y2;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
for (imp = get_implementation (); imp != NULL; imp = imp->delegate)
|
||||
tx1 = ty1 = INT64_MAX;
|
||||
tx2 = ty2 = INT64_MIN;
|
||||
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
const pixman_fast_path_t *info = imp->fast_paths;
|
||||
pixman_fixed_48_16_t tx, ty;
|
||||
pixman_vector_t v;
|
||||
|
||||
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;
|
||||
v.vector[0] = (i & 0x01)? x1 : x2;
|
||||
v.vector[1] = (i & 0x02)? y1 : y2;
|
||||
v.vector[2] = pixman_fixed_1;
|
||||
|
||||
/* 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;
|
||||
if (!pixman_transform_point (transform, &v))
|
||||
return FALSE;
|
||||
|
||||
goto update_cache;
|
||||
}
|
||||
tx = (pixman_fixed_48_16_t)v.vector[0];
|
||||
ty = (pixman_fixed_48_16_t)v.vector[1];
|
||||
|
||||
++info;
|
||||
}
|
||||
if (tx < tx1)
|
||||
tx1 = tx;
|
||||
if (ty < ty1)
|
||||
ty1 = ty;
|
||||
if (tx > tx2)
|
||||
tx2 = tx;
|
||||
if (ty > ty2)
|
||||
ty2 = ty;
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
update_cache:
|
||||
if (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;
|
||||
}
|
||||
transformed->x1 = tx1;
|
||||
transformed->y1 = ty1;
|
||||
transformed->x2 = tx2;
|
||||
transformed->y2 = ty2;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static pixman_bool_t
|
||||
compute_sample_extents (pixman_transform_t *transform,
|
||||
pixman_box32_t *extents, int x, int y,
|
||||
pixman_fixed_t x_off, pixman_fixed_t y_off,
|
||||
pixman_fixed_t width, pixman_fixed_t height)
|
||||
{
|
||||
pixman_fixed_t x1, y1, x2, y2;
|
||||
pixman_fixed_48_16_t tx1, ty1, tx2, ty2;
|
||||
|
||||
/* We have checked earlier that (extents->x1 - x) etc. fit in a pixman_fixed_t */
|
||||
x1 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->x1 - x) + pixman_fixed_1 / 2;
|
||||
y1 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->y1 - y) + pixman_fixed_1 / 2;
|
||||
x2 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->x2 - x) - pixman_fixed_1 / 2;
|
||||
y2 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->y2 - y) - pixman_fixed_1 / 2;
|
||||
|
||||
if (!transform)
|
||||
{
|
||||
tx1 = (pixman_fixed_48_16_t)x1;
|
||||
ty1 = (pixman_fixed_48_16_t)y1;
|
||||
tx2 = (pixman_fixed_48_16_t)x2;
|
||||
ty2 = (pixman_fixed_48_16_t)y2;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Silence GCC */
|
||||
tx1 = ty1 = tx2 = ty2 = 0;
|
||||
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
pixman_fixed_48_16_t tx, ty;
|
||||
pixman_vector_t v;
|
||||
|
||||
v.vector[0] = (i & 0x01)? x1 : x2;
|
||||
v.vector[1] = (i & 0x02)? y1 : y2;
|
||||
v.vector[2] = pixman_fixed_1;
|
||||
|
||||
if (!pixman_transform_point (transform, &v))
|
||||
return FALSE;
|
||||
|
||||
tx = (pixman_fixed_48_16_t)v.vector[0];
|
||||
ty = (pixman_fixed_48_16_t)v.vector[1];
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
tx1 = tx;
|
||||
ty1 = ty;
|
||||
tx2 = tx;
|
||||
ty2 = ty;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tx < tx1)
|
||||
tx1 = tx;
|
||||
if (ty < ty1)
|
||||
ty1 = ty;
|
||||
if (tx > tx2)
|
||||
tx2 = tx;
|
||||
if (ty > ty2)
|
||||
ty2 = ty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Expand the source area by a tiny bit so account of different rounding that
|
||||
* may happen during sampling. Note that (8 * pixman_fixed_e) is very far from
|
||||
* 0.5 so this won't cause the area computed to be overly pessimistic.
|
||||
*/
|
||||
tx1 += x_off - 8 * pixman_fixed_e;
|
||||
ty1 += y_off - 8 * pixman_fixed_e;
|
||||
tx2 += x_off + width + 8 * pixman_fixed_e;
|
||||
ty2 += y_off + height + 8 * pixman_fixed_e;
|
||||
|
||||
if (tx1 < pixman_min_fixed_48_16 || tx1 > pixman_max_fixed_48_16 ||
|
||||
ty1 < pixman_min_fixed_48_16 || ty1 > pixman_max_fixed_48_16 ||
|
||||
tx2 < pixman_min_fixed_48_16 || tx2 > pixman_max_fixed_48_16 ||
|
||||
ty2 < pixman_min_fixed_48_16 || ty2 > pixman_max_fixed_48_16)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
extents->x1 = pixman_fixed_to_int (tx1);
|
||||
extents->y1 = pixman_fixed_to_int (ty1);
|
||||
extents->x2 = pixman_fixed_to_int (tx2) + 1;
|
||||
extents->y2 = pixman_fixed_to_int (ty2) + 1;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
#define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX))
|
||||
#define ABS(f) (((f) < 0)? (-(f)) : (f))
|
||||
#define IS_16_16(f) (((f) >= pixman_min_fixed_48_16 && ((f) <= pixman_max_fixed_48_16)))
|
||||
|
||||
static pixman_bool_t
|
||||
analyze_extent (pixman_image_t *image, int x, int y,
|
||||
const pixman_box32_t *extents, uint32_t *flags)
|
||||
analyze_extent (pixman_image_t *image,
|
||||
const pixman_box32_t *extents,
|
||||
uint32_t *flags)
|
||||
{
|
||||
pixman_transform_t *transform;
|
||||
pixman_fixed_t *params;
|
||||
pixman_fixed_t x_off, y_off;
|
||||
pixman_fixed_t width, height;
|
||||
pixman_box32_t ex;
|
||||
pixman_fixed_t *params;
|
||||
box_48_16_t transformed;
|
||||
pixman_box32_t exp_extents;
|
||||
|
||||
if (!image)
|
||||
return TRUE;
|
||||
@ -600,10 +417,10 @@ analyze_extent (pixman_image_t *image, int x, int y,
|
||||
* check here that the expanded-by-one source
|
||||
* extents in destination space fits in 16 bits
|
||||
*/
|
||||
if (!IS_16BIT (extents->x1 - x - 1) ||
|
||||
!IS_16BIT (extents->y1 - y - 1) ||
|
||||
!IS_16BIT (extents->x2 - x + 1) ||
|
||||
!IS_16BIT (extents->y2 - y + 1))
|
||||
if (!IS_16BIT (extents->x1 - 1) ||
|
||||
!IS_16BIT (extents->y1 - 1) ||
|
||||
!IS_16BIT (extents->x2 + 1) ||
|
||||
!IS_16BIT (extents->y2 + 1))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@ -618,18 +435,16 @@ analyze_extent (pixman_image_t *image, int x, int y,
|
||||
if (image->bits.width >= 0x7fff || image->bits.height >= 0x7fff)
|
||||
return FALSE;
|
||||
|
||||
#define ID_AND_NEAREST (FAST_PATH_ID_TRANSFORM | FAST_PATH_NEAREST_FILTER)
|
||||
|
||||
if ((image->common.flags & ID_AND_NEAREST) == ID_AND_NEAREST &&
|
||||
extents->x1 - x >= 0 &&
|
||||
extents->y1 - y >= 0 &&
|
||||
extents->x2 - x <= image->bits.width &&
|
||||
extents->y2 - y <= image->bits.height)
|
||||
if ((image->common.flags & FAST_PATH_ID_TRANSFORM) == FAST_PATH_ID_TRANSFORM &&
|
||||
extents->x1 >= 0 &&
|
||||
extents->y1 >= 0 &&
|
||||
extents->x2 <= image->bits.width &&
|
||||
extents->y2 <= image->bits.height)
|
||||
{
|
||||
*flags |= FAST_PATH_SAMPLES_COVER_CLIP;
|
||||
*flags |= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
switch (image->common.filter)
|
||||
{
|
||||
case PIXMAN_FILTER_CONVOLUTION:
|
||||
@ -640,6 +455,14 @@ analyze_extent (pixman_image_t *image, int x, int y,
|
||||
height = params[1];
|
||||
break;
|
||||
|
||||
case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
|
||||
params = image->common.filter_params;
|
||||
x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1);
|
||||
y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1);
|
||||
width = params[0];
|
||||
height = params[1];
|
||||
break;
|
||||
|
||||
case PIXMAN_FILTER_GOOD:
|
||||
case PIXMAN_FILTER_BEST:
|
||||
case PIXMAN_FILTER_BILINEAR:
|
||||
@ -660,17 +483,6 @@ analyze_extent (pixman_image_t *image, int x, int y,
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Check whether the non-expanded, transformed extent is entirely within
|
||||
* the source image, and set the FAST_PATH_SAMPLES_COVER_CLIP if it is.
|
||||
*/
|
||||
ex = *extents;
|
||||
if (compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height) &&
|
||||
ex.x1 >= 0 && ex.y1 >= 0 &&
|
||||
ex.x2 <= image->bits.width && ex.y2 <= image->bits.height)
|
||||
{
|
||||
*flags |= FAST_PATH_SAMPLES_COVER_CLIP;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -680,18 +492,58 @@ analyze_extent (pixman_image_t *image, int x, int y,
|
||||
height = 0;
|
||||
}
|
||||
|
||||
/* Check that the extents expanded by one don't overflow. This ensures that
|
||||
* compositing functions can simply walk the source space using 16.16
|
||||
* variables without worrying about overflow.
|
||||
*/
|
||||
ex.x1 = extents->x1 - 1;
|
||||
ex.y1 = extents->y1 - 1;
|
||||
ex.x2 = extents->x2 + 1;
|
||||
ex.y2 = extents->y2 + 1;
|
||||
|
||||
if (!compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height))
|
||||
if (!compute_transformed_extents (transform, extents, &transformed))
|
||||
return FALSE;
|
||||
|
||||
/* Expand the source area by a tiny bit so account of different rounding that
|
||||
* may happen during sampling. Note that (8 * pixman_fixed_e) is very far from
|
||||
* 0.5 so this won't cause the area computed to be overly pessimistic.
|
||||
*/
|
||||
transformed.x1 -= 8 * pixman_fixed_e;
|
||||
transformed.y1 -= 8 * pixman_fixed_e;
|
||||
transformed.x2 += 8 * pixman_fixed_e;
|
||||
transformed.y2 += 8 * pixman_fixed_e;
|
||||
|
||||
if (image->common.type == BITS)
|
||||
{
|
||||
if (pixman_fixed_to_int (transformed.x1) >= 0 &&
|
||||
pixman_fixed_to_int (transformed.y1) >= 0 &&
|
||||
pixman_fixed_to_int (transformed.x2) < image->bits.width &&
|
||||
pixman_fixed_to_int (transformed.y2) < image->bits.height)
|
||||
{
|
||||
*flags |= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
|
||||
}
|
||||
|
||||
if (pixman_fixed_to_int (transformed.x1 - pixman_fixed_1 / 2) >= 0 &&
|
||||
pixman_fixed_to_int (transformed.y1 - pixman_fixed_1 / 2) >= 0 &&
|
||||
pixman_fixed_to_int (transformed.x2 + pixman_fixed_1 / 2) < image->bits.width &&
|
||||
pixman_fixed_to_int (transformed.y2 + pixman_fixed_1 / 2) < image->bits.height)
|
||||
{
|
||||
*flags |= FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check we don't overflow when the destination extents are expanded by one.
|
||||
* This ensures that compositing functions can simply walk the source space
|
||||
* using 16.16 variables without worrying about overflow.
|
||||
*/
|
||||
exp_extents = *extents;
|
||||
exp_extents.x1 -= 1;
|
||||
exp_extents.y1 -= 1;
|
||||
exp_extents.x2 += 1;
|
||||
exp_extents.y2 += 1;
|
||||
|
||||
if (!compute_transformed_extents (transform, &exp_extents, &transformed))
|
||||
return FALSE;
|
||||
|
||||
if (!IS_16_16 (transformed.x1 + x_off - 8 * pixman_fixed_e) ||
|
||||
!IS_16_16 (transformed.y1 + y_off - 8 * pixman_fixed_e) ||
|
||||
!IS_16_16 (transformed.x2 + x_off + 8 * pixman_fixed_e + width) ||
|
||||
!IS_16_16 (transformed.y2 + y_off + 8 * pixman_fixed_e + height))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -729,18 +581,13 @@ pixman_image_composite32 (pixman_op_t op,
|
||||
int32_t height)
|
||||
{
|
||||
pixman_format_code_t src_format, mask_format, dest_format;
|
||||
uint32_t src_flags, mask_flags, dest_flags;
|
||||
pixman_region32_t region;
|
||||
pixman_box32_t *extents;
|
||||
uint32_t *src_bits;
|
||||
int src_dx, src_dy;
|
||||
uint32_t *mask_bits;
|
||||
int mask_dx, mask_dy;
|
||||
uint32_t *dest_bits;
|
||||
int dest_dx, dest_dy;
|
||||
pixman_bool_t need_workaround;
|
||||
pixman_box32_t extents;
|
||||
pixman_implementation_t *imp;
|
||||
pixman_composite_func_t func;
|
||||
pixman_composite_info_t info;
|
||||
const pixman_box32_t *pbox;
|
||||
int n;
|
||||
|
||||
_pixman_image_validate (src);
|
||||
if (mask)
|
||||
@ -748,26 +595,27 @@ pixman_image_composite32 (pixman_op_t op,
|
||||
_pixman_image_validate (dest);
|
||||
|
||||
src_format = src->common.extended_format_code;
|
||||
src_flags = src->common.flags;
|
||||
info.src_flags = src->common.flags;
|
||||
|
||||
if (mask)
|
||||
if (mask && !(mask->common.flags & FAST_PATH_IS_OPAQUE))
|
||||
{
|
||||
mask_format = mask->common.extended_format_code;
|
||||
mask_flags = mask->common.flags;
|
||||
info.mask_flags = mask->common.flags;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask_format = PIXMAN_null;
|
||||
mask_flags = FAST_PATH_IS_OPAQUE;
|
||||
info.mask_flags = FAST_PATH_IS_OPAQUE;
|
||||
}
|
||||
|
||||
dest_format = dest->common.extended_format_code;
|
||||
dest_flags = dest->common.flags;
|
||||
info.dest_flags = dest->common.flags;
|
||||
|
||||
/* Check for pixbufs */
|
||||
if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) &&
|
||||
(src->type == BITS && src->bits.bits == mask->bits.bits) &&
|
||||
(src->common.repeat == mask->common.repeat) &&
|
||||
(info.src_flags & info.mask_flags & FAST_PATH_ID_TRANSFORM) &&
|
||||
(src_x == mask_x && src_y == mask_y))
|
||||
{
|
||||
if (src_format == PIXMAN_x8b8g8r8)
|
||||
@ -776,89 +624,92 @@ pixman_image_composite32 (pixman_op_t op,
|
||||
src_format = mask_format = PIXMAN_rpixbuf;
|
||||
}
|
||||
|
||||
/* Check for workaround */
|
||||
need_workaround = (src_flags | mask_flags | dest_flags) & FAST_PATH_NEEDS_WORKAROUND;
|
||||
|
||||
if (need_workaround)
|
||||
{
|
||||
apply_workaround (src, &src_x, &src_y, &src_bits, &src_dx, &src_dy);
|
||||
apply_workaround (mask, &mask_x, &mask_y, &mask_bits, &mask_dx, &mask_dy);
|
||||
apply_workaround (dest, &dest_x, &dest_y, &dest_bits, &dest_dx, &dest_dy);
|
||||
}
|
||||
|
||||
pixman_region32_init (®ion);
|
||||
|
||||
if (!pixman_compute_composite_region32 (
|
||||
if (!_pixman_compute_composite_region32 (
|
||||
®ion, src, mask, dest,
|
||||
src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
extents = pixman_region32_extents (®ion);
|
||||
extents = *pixman_region32_extents (®ion);
|
||||
|
||||
if (!analyze_extent (src, dest_x - src_x, dest_y - src_y, extents, &src_flags))
|
||||
extents.x1 -= dest_x - src_x;
|
||||
extents.y1 -= dest_y - src_y;
|
||||
extents.x2 -= dest_x - src_x;
|
||||
extents.y2 -= dest_y - src_y;
|
||||
|
||||
if (!analyze_extent (src, &extents, &info.src_flags))
|
||||
goto out;
|
||||
|
||||
if (!analyze_extent (mask, dest_x - mask_x, dest_y - mask_y, extents, &mask_flags))
|
||||
extents.x1 -= src_x - mask_x;
|
||||
extents.y1 -= src_y - mask_y;
|
||||
extents.x2 -= src_x - mask_x;
|
||||
extents.y2 -= src_y - mask_y;
|
||||
|
||||
if (!analyze_extent (mask, &extents, &info.mask_flags))
|
||||
goto out;
|
||||
|
||||
/* If the clip is within the source samples, and the samples are opaque,
|
||||
* then the source is effectively opaque.
|
||||
/* If the clip is within the source samples, and the samples are
|
||||
* opaque, then the source is effectively opaque.
|
||||
*/
|
||||
#define BOTH (FAST_PATH_SAMPLES_OPAQUE | FAST_PATH_SAMPLES_COVER_CLIP)
|
||||
#define NEAREST_OPAQUE (FAST_PATH_SAMPLES_OPAQUE | \
|
||||
FAST_PATH_NEAREST_FILTER | \
|
||||
FAST_PATH_SAMPLES_COVER_CLIP_NEAREST)
|
||||
#define BILINEAR_OPAQUE (FAST_PATH_SAMPLES_OPAQUE | \
|
||||
FAST_PATH_BILINEAR_FILTER | \
|
||||
FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR)
|
||||
|
||||
if ((info.src_flags & NEAREST_OPAQUE) == NEAREST_OPAQUE ||
|
||||
(info.src_flags & BILINEAR_OPAQUE) == BILINEAR_OPAQUE)
|
||||
{
|
||||
info.src_flags |= FAST_PATH_IS_OPAQUE;
|
||||
}
|
||||
|
||||
if ((info.mask_flags & NEAREST_OPAQUE) == NEAREST_OPAQUE ||
|
||||
(info.mask_flags & BILINEAR_OPAQUE) == BILINEAR_OPAQUE)
|
||||
{
|
||||
info.mask_flags |= FAST_PATH_IS_OPAQUE;
|
||||
}
|
||||
|
||||
if ((src_flags & BOTH) == BOTH)
|
||||
src_flags |= FAST_PATH_IS_OPAQUE;
|
||||
|
||||
if ((mask_flags & BOTH) == BOTH)
|
||||
mask_flags |= FAST_PATH_IS_OPAQUE;
|
||||
|
||||
/*
|
||||
* Check if we can replace our operator by a simpler one
|
||||
* if the src or dest are opaque. The output operator should be
|
||||
* mathematically equivalent to the source.
|
||||
*/
|
||||
op = optimize_operator (op, src_flags, mask_flags, dest_flags);
|
||||
if (op == PIXMAN_OP_DST)
|
||||
goto out;
|
||||
info.op = optimize_operator (op, info.src_flags, info.mask_flags, info.dest_flags);
|
||||
|
||||
if (lookup_composite_function (op,
|
||||
src_format, src_flags,
|
||||
mask_format, mask_flags,
|
||||
dest_format, dest_flags,
|
||||
&imp, &func))
|
||||
_pixman_implementation_lookup_composite (
|
||||
get_implementation (), info.op,
|
||||
src_format, info.src_flags,
|
||||
mask_format, info.mask_flags,
|
||||
dest_format, info.dest_flags,
|
||||
&imp, &func);
|
||||
|
||||
info.src_image = src;
|
||||
info.mask_image = mask;
|
||||
info.dest_image = dest;
|
||||
|
||||
pbox = pixman_region32_rectangles (®ion, &n);
|
||||
|
||||
while (n--)
|
||||
{
|
||||
const pixman_box32_t *pbox;
|
||||
int n;
|
||||
info.src_x = pbox->x1 + src_x - dest_x;
|
||||
info.src_y = pbox->y1 + src_y - dest_y;
|
||||
info.mask_x = pbox->x1 + mask_x - dest_x;
|
||||
info.mask_y = pbox->y1 + mask_y - dest_y;
|
||||
info.dest_x = pbox->x1;
|
||||
info.dest_y = pbox->y1;
|
||||
info.width = pbox->x2 - pbox->x1;
|
||||
info.height = pbox->y2 - pbox->y1;
|
||||
|
||||
pbox = pixman_region32_rectangles (®ion, &n);
|
||||
|
||||
while (n--)
|
||||
{
|
||||
func (imp, op,
|
||||
src, mask, dest,
|
||||
pbox->x1 + src_x - dest_x,
|
||||
pbox->y1 + src_y - dest_y,
|
||||
pbox->x1 + mask_x - dest_x,
|
||||
pbox->y1 + mask_y - dest_y,
|
||||
pbox->x1,
|
||||
pbox->y1,
|
||||
pbox->x2 - pbox->x1,
|
||||
pbox->y2 - pbox->y1);
|
||||
|
||||
pbox++;
|
||||
}
|
||||
func (imp, &info);
|
||||
|
||||
pbox++;
|
||||
}
|
||||
|
||||
out:
|
||||
if (need_workaround)
|
||||
{
|
||||
unapply_workaround (src, src_bits, src_dx, src_dy);
|
||||
unapply_workaround (mask, mask_bits, mask_dx, mask_dy);
|
||||
unapply_workaround (dest, dest_bits, dest_dx, dest_dy);
|
||||
}
|
||||
|
||||
pixman_region32_fini (®ion);
|
||||
}
|
||||
|
||||
@ -889,8 +740,8 @@ pixman_blt (uint32_t *src_bits,
|
||||
int dst_bpp,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
int dest_x,
|
||||
int dest_y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
@ -898,7 +749,7 @@ pixman_blt (uint32_t *src_bits,
|
||||
src_bits, dst_bits, src_stride, dst_stride,
|
||||
src_bpp, dst_bpp,
|
||||
src_x, src_y,
|
||||
dst_x, dst_y,
|
||||
dest_x, dest_y,
|
||||
width, height);
|
||||
}
|
||||
|
||||
@ -910,10 +761,10 @@ pixman_fill (uint32_t *bits,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
uint32_t xor)
|
||||
uint32_t filler)
|
||||
{
|
||||
return _pixman_implementation_fill (
|
||||
get_implementation(), bits, stride, bpp, x, y, width, height, xor);
|
||||
get_implementation(), bits, stride, bpp, x, y, width, height, filler);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
@ -927,9 +778,9 @@ color_to_uint32 (const pixman_color_t *color)
|
||||
}
|
||||
|
||||
static pixman_bool_t
|
||||
color_to_pixel (pixman_color_t * color,
|
||||
uint32_t * pixel,
|
||||
pixman_format_code_t format)
|
||||
color_to_pixel (const pixman_color_t *color,
|
||||
uint32_t * pixel,
|
||||
pixman_format_code_t format)
|
||||
{
|
||||
uint32_t c = color_to_uint32 (color);
|
||||
|
||||
@ -939,9 +790,12 @@ color_to_pixel (pixman_color_t * color,
|
||||
format == PIXMAN_x8b8g8r8 ||
|
||||
format == PIXMAN_b8g8r8a8 ||
|
||||
format == PIXMAN_b8g8r8x8 ||
|
||||
format == PIXMAN_r8g8b8a8 ||
|
||||
format == PIXMAN_r8g8b8x8 ||
|
||||
format == PIXMAN_r5g6b5 ||
|
||||
format == PIXMAN_b5g6r5 ||
|
||||
format == PIXMAN_a8))
|
||||
format == PIXMAN_a8 ||
|
||||
format == PIXMAN_a1))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@ -960,12 +814,16 @@ color_to_pixel (pixman_color_t * color,
|
||||
((c & 0x0000ff00) << 8) |
|
||||
((c & 0x000000ff) << 24);
|
||||
}
|
||||
if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_RGBA)
|
||||
c = ((c & 0xff000000) >> 24) | (c << 8);
|
||||
|
||||
if (format == PIXMAN_a8)
|
||||
if (format == PIXMAN_a1)
|
||||
c = c >> 31;
|
||||
else if (format == PIXMAN_a8)
|
||||
c = c >> 24;
|
||||
else if (format == PIXMAN_r5g6b5 ||
|
||||
format == PIXMAN_b5g6r5)
|
||||
c = CONVERT_8888_TO_0565 (c);
|
||||
c = convert_8888_to_0565 (c);
|
||||
|
||||
#if 0
|
||||
printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue);
|
||||
@ -979,7 +837,7 @@ color_to_pixel (pixman_color_t * color,
|
||||
PIXMAN_EXPORT pixman_bool_t
|
||||
pixman_image_fill_rectangles (pixman_op_t op,
|
||||
pixman_image_t * dest,
|
||||
pixman_color_t * color,
|
||||
const pixman_color_t * color,
|
||||
int n_rects,
|
||||
const pixman_rectangle16_t *rects)
|
||||
{
|
||||
@ -1018,7 +876,7 @@ pixman_image_fill_rectangles (pixman_op_t op,
|
||||
PIXMAN_EXPORT pixman_bool_t
|
||||
pixman_image_fill_boxes (pixman_op_t op,
|
||||
pixman_image_t * dest,
|
||||
pixman_color_t * color,
|
||||
const pixman_color_t *color,
|
||||
int n_boxes,
|
||||
const pixman_box32_t *boxes)
|
||||
{
|
||||
@ -1163,11 +1021,14 @@ pixman_format_supported_source (pixman_format_code_t format)
|
||||
case PIXMAN_a2r10g10b10:
|
||||
case PIXMAN_x2r10g10b10:
|
||||
case PIXMAN_a8r8g8b8:
|
||||
case PIXMAN_a8r8g8b8_sRGB:
|
||||
case PIXMAN_x8r8g8b8:
|
||||
case PIXMAN_a8b8g8r8:
|
||||
case PIXMAN_x8b8g8r8:
|
||||
case PIXMAN_b8g8r8a8:
|
||||
case PIXMAN_b8g8r8x8:
|
||||
case PIXMAN_r8g8b8a8:
|
||||
case PIXMAN_r8g8b8x8:
|
||||
case PIXMAN_r8g8b8:
|
||||
case PIXMAN_b8g8r8:
|
||||
case PIXMAN_r5g6b5:
|
||||
@ -1243,7 +1104,7 @@ PIXMAN_EXPORT pixman_bool_t
|
||||
pixman_compute_composite_region (pixman_region16_t * region,
|
||||
pixman_image_t * src_image,
|
||||
pixman_image_t * mask_image,
|
||||
pixman_image_t * dst_image,
|
||||
pixman_image_t * dest_image,
|
||||
int16_t src_x,
|
||||
int16_t src_y,
|
||||
int16_t mask_x,
|
||||
@ -1258,8 +1119,8 @@ pixman_compute_composite_region (pixman_region16_t * region,
|
||||
|
||||
pixman_region32_init (&r32);
|
||||
|
||||
retval = pixman_compute_composite_region32 (
|
||||
&r32, src_image, mask_image, dst_image,
|
||||
retval = _pixman_compute_composite_region32 (
|
||||
&r32, src_image, mask_image, dest_image,
|
||||
src_x, src_y, mask_x, mask_y, dest_x, dest_y,
|
||||
width, height);
|
||||
|
||||
|
@ -226,6 +226,9 @@ pixman_bool_t pixman_transform_is_inverse (const struct pixman_transform *
|
||||
/*
|
||||
* Floating point matrices
|
||||
*/
|
||||
typedef struct pixman_f_transform pixman_f_transform_t;
|
||||
typedef struct pixman_f_vector pixman_f_vector_t;
|
||||
|
||||
struct pixman_f_vector
|
||||
{
|
||||
double v[3];
|
||||
@ -289,7 +292,28 @@ typedef enum
|
||||
PIXMAN_FILTER_BEST,
|
||||
PIXMAN_FILTER_NEAREST,
|
||||
PIXMAN_FILTER_BILINEAR,
|
||||
PIXMAN_FILTER_CONVOLUTION
|
||||
PIXMAN_FILTER_CONVOLUTION,
|
||||
|
||||
/* The SEPARABLE_CONVOLUTION filter takes the following parameters:
|
||||
*
|
||||
* width: integer given as 16.16 fixpoint number
|
||||
* height: integer given as 16.16 fixpoint number
|
||||
* x_phase_bits: integer given as 16.16 fixpoint
|
||||
* y_phase_bits: integer given as 16.16 fixpoint
|
||||
* xtables: (1 << x_phase_bits) tables of size width
|
||||
* ytables: (1 << y_phase_bits) tables of size height
|
||||
*
|
||||
* When sampling at (x, y), the location is first rounded to one of
|
||||
* n_x_phases * n_y_phases subpixel positions. These subpixel positions
|
||||
* determine an xtable and a ytable to use.
|
||||
*
|
||||
* Conceptually a width x height matrix is then formed in which each entry
|
||||
* is the product of the corresponding entries in the x and y tables.
|
||||
* This matrix is then aligned with the image pixels such that its center
|
||||
* is as close as possible to the subpixel location chosen earlier. Then
|
||||
* the image is convolved with the matrix and the resulting pixel returned.
|
||||
*/
|
||||
PIXMAN_FILTER_SEPARABLE_CONVOLUTION
|
||||
} pixman_filter_t;
|
||||
|
||||
typedef enum
|
||||
@ -466,6 +490,7 @@ pixman_bool_t pixman_region_equal (pixman_region16_t *reg
|
||||
pixman_bool_t pixman_region_selfcheck (pixman_region16_t *region);
|
||||
void pixman_region_reset (pixman_region16_t *region,
|
||||
pixman_box16_t *box);
|
||||
void pixman_region_clear (pixman_region16_t *region);
|
||||
/*
|
||||
* 32 bit regions
|
||||
*/
|
||||
@ -560,6 +585,7 @@ pixman_bool_t pixman_region32_equal (pixman_region32_t *r
|
||||
pixman_bool_t pixman_region32_selfcheck (pixman_region32_t *region);
|
||||
void pixman_region32_reset (pixman_region32_t *region,
|
||||
pixman_box32_t *box);
|
||||
void pixman_region32_clear (pixman_region32_t *region);
|
||||
|
||||
|
||||
/* Copy / Fill / Misc */
|
||||
@ -571,8 +597,8 @@ pixman_bool_t pixman_blt (uint32_t *src_bits,
|
||||
int dst_bpp,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
int dest_x,
|
||||
int dest_y,
|
||||
int width,
|
||||
int height);
|
||||
pixman_bool_t pixman_fill (uint32_t *bits,
|
||||
@ -650,11 +676,14 @@ struct pixman_indexed
|
||||
#define PIXMAN_TYPE_YUY2 6
|
||||
#define PIXMAN_TYPE_YV12 7
|
||||
#define PIXMAN_TYPE_BGRA 8
|
||||
#define PIXMAN_TYPE_RGBA 9
|
||||
#define PIXMAN_TYPE_ARGB_SRGB 10
|
||||
|
||||
#define PIXMAN_FORMAT_COLOR(f) \
|
||||
(PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_ARGB || \
|
||||
PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_ABGR || \
|
||||
PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_BGRA)
|
||||
PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_BGRA || \
|
||||
PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_RGBA)
|
||||
|
||||
/* 32bpp formats */
|
||||
typedef enum {
|
||||
@ -664,12 +693,17 @@ typedef enum {
|
||||
PIXMAN_x8b8g8r8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,0,8,8,8),
|
||||
PIXMAN_b8g8r8a8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_BGRA,8,8,8,8),
|
||||
PIXMAN_b8g8r8x8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_BGRA,0,8,8,8),
|
||||
PIXMAN_r8g8b8a8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_RGBA,8,8,8,8),
|
||||
PIXMAN_r8g8b8x8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_RGBA,0,8,8,8),
|
||||
PIXMAN_x14r6g6b6 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB,0,6,6,6),
|
||||
PIXMAN_x2r10g10b10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB,0,10,10,10),
|
||||
PIXMAN_a2r10g10b10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB,2,10,10,10),
|
||||
PIXMAN_x2b10g10r10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,0,10,10,10),
|
||||
PIXMAN_a2b10g10r10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,2,10,10,10),
|
||||
|
||||
/* sRGB formats */
|
||||
PIXMAN_a8r8g8b8_sRGB = PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB_SRGB,8,8,8,8),
|
||||
|
||||
/* 24bpp formats */
|
||||
PIXMAN_r8g8b8 = PIXMAN_FORMAT(24,PIXMAN_TYPE_ARGB,0,8,8,8),
|
||||
PIXMAN_b8g8r8 = PIXMAN_FORMAT(24,PIXMAN_TYPE_ABGR,0,8,8,8),
|
||||
@ -727,18 +761,18 @@ pixman_bool_t pixman_format_supported_destination (pixman_format_code_t format);
|
||||
pixman_bool_t pixman_format_supported_source (pixman_format_code_t format);
|
||||
|
||||
/* Constructors */
|
||||
pixman_image_t *pixman_image_create_solid_fill (pixman_color_t *color);
|
||||
pixman_image_t *pixman_image_create_linear_gradient (pixman_point_fixed_t *p1,
|
||||
pixman_point_fixed_t *p2,
|
||||
pixman_image_t *pixman_image_create_solid_fill (const pixman_color_t *color);
|
||||
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 *pixman_image_create_radial_gradient (pixman_point_fixed_t *inner,
|
||||
pixman_point_fixed_t *outer,
|
||||
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 *pixman_image_create_conical_gradient (pixman_point_fixed_t *center,
|
||||
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);
|
||||
@ -747,6 +781,11 @@ pixman_image_t *pixman_image_create_bits (pixman_format_code_t
|
||||
int height,
|
||||
uint32_t *bits,
|
||||
int rowstride_bytes);
|
||||
pixman_image_t *pixman_image_create_bits_no_clear (pixman_format_code_t format,
|
||||
int width,
|
||||
int height,
|
||||
uint32_t * bits,
|
||||
int rowstride_bytes);
|
||||
|
||||
/* Destructor */
|
||||
pixman_image_t *pixman_image_ref (pixman_image_t *image);
|
||||
@ -792,14 +831,41 @@ int pixman_image_get_height (pixman_image_t
|
||||
int pixman_image_get_stride (pixman_image_t *image); /* in bytes */
|
||||
int pixman_image_get_depth (pixman_image_t *image);
|
||||
pixman_format_code_t pixman_image_get_format (pixman_image_t *image);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PIXMAN_KERNEL_IMPULSE,
|
||||
PIXMAN_KERNEL_BOX,
|
||||
PIXMAN_KERNEL_LINEAR,
|
||||
PIXMAN_KERNEL_CUBIC,
|
||||
PIXMAN_KERNEL_GAUSSIAN,
|
||||
PIXMAN_KERNEL_LANCZOS2,
|
||||
PIXMAN_KERNEL_LANCZOS3,
|
||||
PIXMAN_KERNEL_LANCZOS3_STRETCHED /* Jim Blinn's 'nice' filter */
|
||||
} pixman_kernel_t;
|
||||
|
||||
/* Create the parameter list for a SEPARABLE_CONVOLUTION filter
|
||||
* with the given kernels and scale parameters.
|
||||
*/
|
||||
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);
|
||||
|
||||
pixman_bool_t pixman_image_fill_rectangles (pixman_op_t op,
|
||||
pixman_image_t *image,
|
||||
pixman_color_t *color,
|
||||
const pixman_color_t *color,
|
||||
int n_rects,
|
||||
const pixman_rectangle16_t *rects);
|
||||
pixman_bool_t pixman_image_fill_boxes (pixman_op_t op,
|
||||
pixman_image_t *dest,
|
||||
pixman_color_t *color,
|
||||
const pixman_color_t *color,
|
||||
int n_boxes,
|
||||
const pixman_box32_t *boxes);
|
||||
|
||||
@ -807,7 +873,7 @@ pixman_bool_t pixman_image_fill_boxes (pixman_op_t
|
||||
pixman_bool_t pixman_compute_composite_region (pixman_region16_t *region,
|
||||
pixman_image_t *src_image,
|
||||
pixman_image_t *mask_image,
|
||||
pixman_image_t *dst_image,
|
||||
pixman_image_t *dest_image,
|
||||
int16_t src_x,
|
||||
int16_t src_y,
|
||||
int16_t mask_x,
|
||||
@ -841,19 +907,84 @@ void pixman_image_composite32 (pixman_op_t op,
|
||||
int32_t width,
|
||||
int32_t height);
|
||||
|
||||
/* Old X servers rely on out-of-bounds accesses when they are asked
|
||||
* to composite with a window as the source. They create a pixman image
|
||||
* pointing to some bogus position in memory, but then they set a clip
|
||||
* region to the position where the actual bits are.
|
||||
/* 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 by default we allow certain out-of-bound access
|
||||
* to happen unless explicitly disabled.
|
||||
* 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.
|
||||
*
|
||||
* Fixed X servers should call this function to disable the workaround.
|
||||
* Since 0.21.2, pixman doesn't do these workarounds anymore, so now this
|
||||
* function is a no-op.
|
||||
*/
|
||||
void pixman_disable_out_of_bounds_workaround (void);
|
||||
void pixman_disable_out_of_bounds_workaround (void);
|
||||
|
||||
/*
|
||||
* Glyphs
|
||||
*/
|
||||
typedef struct pixman_glyph_cache_t pixman_glyph_cache_t;
|
||||
typedef struct
|
||||
{
|
||||
int x, y;
|
||||
const void *glyph;
|
||||
} pixman_glyph_t;
|
||||
|
||||
pixman_glyph_cache_t *pixman_glyph_cache_create (void);
|
||||
void pixman_glyph_cache_destroy (pixman_glyph_cache_t *cache);
|
||||
void pixman_glyph_cache_freeze (pixman_glyph_cache_t *cache);
|
||||
void pixman_glyph_cache_thaw (pixman_glyph_cache_t *cache);
|
||||
const void * pixman_glyph_cache_lookup (pixman_glyph_cache_t *cache,
|
||||
void *font_key,
|
||||
void *glyph_key);
|
||||
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 *glyph_image);
|
||||
void pixman_glyph_cache_remove (pixman_glyph_cache_t *cache,
|
||||
void *font_key,
|
||||
void *glyph_key);
|
||||
void pixman_glyph_get_extents (pixman_glyph_cache_t *cache,
|
||||
int n_glyphs,
|
||||
pixman_glyph_t *glyphs,
|
||||
pixman_box32_t *extents);
|
||||
pixman_format_code_t pixman_glyph_get_mask_format (pixman_glyph_cache_t *cache,
|
||||
int n_glyphs,
|
||||
const pixman_glyph_t *glyphs);
|
||||
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);
|
||||
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);
|
||||
|
||||
/*
|
||||
* Trapezoids
|
||||
@ -862,6 +993,7 @@ typedef struct pixman_edge pixman_edge_t;
|
||||
typedef struct pixman_trapezoid pixman_trapezoid_t;
|
||||
typedef struct pixman_trap pixman_trap_t;
|
||||
typedef struct pixman_span_fix pixman_span_fix_t;
|
||||
typedef struct pixman_triangle pixman_triangle_t;
|
||||
|
||||
/*
|
||||
* An edge structure. This represents a single polygon edge
|
||||
@ -889,6 +1021,10 @@ struct pixman_trapezoid
|
||||
pixman_line_fixed_t left, right;
|
||||
};
|
||||
|
||||
struct pixman_triangle
|
||||
{
|
||||
pixman_point_fixed_t p1, p2, p3;
|
||||
};
|
||||
|
||||
/* whether 't' is a well defined not obviously empty trapezoid */
|
||||
#define pixman_trapezoid_valid(t) \
|
||||
@ -934,7 +1070,7 @@ void pixman_add_traps (pixman_image_t *image,
|
||||
int16_t x_off,
|
||||
int16_t y_off,
|
||||
int ntrap,
|
||||
pixman_trap_t *traps);
|
||||
const pixman_trap_t *traps);
|
||||
void pixman_add_trapezoids (pixman_image_t *image,
|
||||
int16_t x_off,
|
||||
int y_off,
|
||||
@ -944,6 +1080,31 @@ void pixman_rasterize_trapezoid (pixman_image_t *image,
|
||||
const pixman_trapezoid_t *trap,
|
||||
int x_off,
|
||||
int y_off);
|
||||
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);
|
||||
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);
|
||||
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_END_DECLS
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user