imported patch bug_552142_fast_scale_branch_pixman

This commit is contained in:
Doug Turner 2010-03-19 00:04:46 -07:00
Родитель 1ca1cfe558
Коммит 3f254c5006
5 изменённых файлов: 1491 добавлений и 5 удалений

Просмотреть файл

@ -110,6 +110,7 @@ CSRCS = \
pixman-cpu.c \
pixman-edge.c \
pixman-edge-accessors.c \
pixman-fast-path-scale.c \
pixman-fast-path.c \
pixman-general.c \
pixman-gradient-walker.c \

Просмотреть файл

@ -534,6 +534,212 @@ bits_image_fetch_bilinear_no_repeat_8888 (pixman_image_t * ima,
*buffer++ = 0;
}
static void
bits_image_fetch_bilinear_no_repeat_0565 (pixman_image_t * ima,
int offset,
int line,
int width,
uint32_t * buffer,
const uint32_t * mask,
uint32_t mask_bits)
{
bits_image_t *bits = &ima->bits;
pixman_fixed_t x_top, x_bottom, x;
pixman_fixed_t ux_top, ux_bottom, ux;
pixman_vector_t v;
uint32_t top_mask, bottom_mask;
uint16_t *top_row;
uint16_t *bottom_row;
uint32_t *end;
uint16_t zero[2] = { 0, 0 };
int y, y1, y2;
int disty;
int mask_inc;
int w;
/* reference point is the center of the pixel */
v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
v.vector[2] = pixman_fixed_1;
if (!pixman_transform_point_3d (bits->common.transform, &v))
return;
ux = ux_top = ux_bottom = bits->common.transform->matrix[0][0];
x = x_top = x_bottom = v.vector[0] - pixman_fixed_1/2;
y = v.vector[1] - pixman_fixed_1/2;
disty = (y >> 8) & 0xff;
/* Load the pointers to the first and second lines from the source
* image that bilinear code must read.
*
* The main trick in this code is about the check if any line are
* outside of the image;
*
* When I realize that a line (any one) is outside, I change
* the pointer to a dummy area with zeros. Once I change this, I
* must be sure the pointer will not change, so I set the
* variables to each pointer increments inside the loop.
*/
y1 = pixman_fixed_to_int (y);
y2 = y1 + 1;
if (y1 < 0 || y1 >= bits->height)
{
top_row = zero;
x_top = 0;
ux_top = 0;
}
else
{
top_row = bits->bits + y1 * bits->rowstride;
x_top = x;
ux_top = ux;
}
if (y2 < 0 || y2 >= bits->height)
{
bottom_row = zero;
x_bottom = 0;
ux_bottom = 0;
}
else
{
bottom_row = bits->bits + y2 * bits->rowstride;
x_bottom = x;
ux_bottom = ux;
}
/* Instead of checking whether the operation uses the mast in
* each loop iteration, verify this only once and prepare the
* variables to make the code smaller inside the loop.
*/
if (!mask)
{
mask_inc = 0;
mask_bits = 1;
mask = &mask_bits;
}
else
{
/* If have a mask, prepare the variables to check it */
mask_inc = 1;
}
/* If both are zero, then the whole thing is zero */
if (top_row == zero && bottom_row == zero)
{
memset (buffer, 0, width * sizeof (uint32_t));
return;
}
else
{
if (top_row == zero)
{
top_mask = 0;
bottom_mask = 0xff000000;
}
else if (bottom_row == zero)
{
top_mask = 0xff000000;
bottom_mask = 0;
}
else
{
top_mask = 0xff000000;
bottom_mask = 0xff000000;
}
}
end = buffer + width;
/* Zero fill to the left of the image */
while (buffer < end && x < pixman_fixed_minus_1)
{
*buffer++ = 0;
x += ux;
x_top += ux_top;
x_bottom += ux_bottom;
mask += mask_inc;
}
/* Left edge
*/
while (buffer < end && x < 0)
{
uint32_t tr, br;
int32_t distx;
tr = CONVERT_0565_TO_0888 (top_row[pixman_fixed_to_int (x_top) + 1]) | top_mask;
br = CONVERT_0565_TO_0888 (bottom_row[pixman_fixed_to_int (x_bottom) + 1]) | bottom_mask;
distx = (x >> 8) & 0xff;
*buffer++ = bilinear_interpolation (0, tr, 0, br, distx, disty);
x += ux;
x_top += ux_top;
x_bottom += ux_bottom;
mask += mask_inc;
}
/* Main part */
w = pixman_int_to_fixed (bits->width - 1);
while (buffer < end && x < w)
{
if (*mask)
{
uint32_t tl, tr, bl, br;
int32_t distx;
tl = CONVERT_0565_TO_0888 (top_row [pixman_fixed_to_int (x_top)]) | top_mask;
tr = CONVERT_0565_TO_0888 (top_row [pixman_fixed_to_int (x_top) + 1]) | top_mask;
bl = CONVERT_0565_TO_0888 (bottom_row [pixman_fixed_to_int (x_bottom)]) | bottom_mask;
br = CONVERT_0565_TO_0888 (bottom_row [pixman_fixed_to_int (x_bottom) + 1]) | bottom_mask;
distx = (x >> 8) & 0xff;
*buffer = bilinear_interpolation (tl, tr, bl, br, distx, disty);
}
buffer++;
x += ux;
x_top += ux_top;
x_bottom += ux_bottom;
mask += mask_inc;
}
/* Right Edge */
w = pixman_int_to_fixed (bits->width);
while (buffer < end && x < w)
{
if (*mask)
{
uint32_t tl, bl;
int32_t distx;
tl = CONVERT_0565_TO_0888 (top_row [pixman_fixed_to_int (x_top)]) | top_mask;
bl = CONVERT_0565_TO_0888 (bottom_row [pixman_fixed_to_int (x_bottom)]) | bottom_mask;
distx = (x >> 8) & 0xff;
*buffer = bilinear_interpolation (tl, 0, bl, 0, distx, disty);
}
buffer++;
x += ux;
x_top += ux_top;
x_bottom += ux_bottom;
mask += mask_inc;
}
/* Zero fill to the left of the image */
while (buffer < end)
*buffer++ = 0;
}
static force_inline uint32_t
bits_image_fetch_pixel_convolution (bits_image_t *image,
pixman_fixed_t x,
@ -965,14 +1171,26 @@ bits_image_property_changed (pixman_image_t *image)
(bits->common.filter == PIXMAN_FILTER_BILINEAR ||
bits->common.filter == PIXMAN_FILTER_GOOD ||
bits->common.filter == PIXMAN_FILTER_BEST) &&
bits->common.repeat == PIXMAN_REPEAT_NONE &&
(bits->format == PIXMAN_a8r8g8b8 ||
bits->format == PIXMAN_x8r8g8b8))
bits->common.repeat == PIXMAN_REPEAT_NONE)
{
image->common.get_scanline_64 =
_pixman_image_get_scanline_generic_64;
image->common.get_scanline_32 =
bits_image_fetch_bilinear_no_repeat_8888;
if (bits->format == PIXMAN_a8r8g8b8 || bits->format == PIXMAN_x8r8g8b8)
{
image->common.get_scanline_32 =
bits_image_fetch_bilinear_no_repeat_8888;
}
else if (bits->format == PIXMAN_r5g6b5)
{
image->common.get_scanline_32 =
bits_image_fetch_bilinear_no_repeat_0565;
}
else
{
image->common.get_scanline_32 =
bits_image_fetch_transformed;
}
}
else
{

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1529,6 +1529,39 @@ fast_path_composite (pixman_implementation_t *imp,
int32_t width,
int32_t height)
{
/*
* In some cases, single pass fast path composite operation
* can be also run for the cases when source image has
* transform and repeat set. For now, only NEAREST transform
* is supported and destination image should have trivial
* clipping only (one clipping box at most). Additionally,
* transform should only perform scaling (but no rotation).
*/
if (src->type == BITS &&
src->common.transform &&
!mask &&
!src->common.alpha_map && !dest->common.alpha_map &&
src->common.filter == PIXMAN_FILTER_NEAREST &&
!src->bits.read_func && !src->bits.write_func &&
!dest->bits.read_func && !dest->bits.write_func)
{
if (src->common.transform->matrix[0][1] == 0 &&
src->common.transform->matrix[1][0] == 0 &&
src->common.transform->matrix[2][0] == 0 &&
src->common.transform->matrix[2][1] == 0 &&
src->common.transform->matrix[2][2] == pixman_fixed_1 &&
(!dest->common.have_clip_region ||
dest->common.clip_region.data == NULL))
{
if (_pixman_run_fast_path_scale (op, src, mask, dest, src_x, src_y,
mask_x, mask_y, dest_x, dest_y,
width, height))
{
return;
}
}
}
if (src->type == BITS
&& src->common.transform
&& !mask

Просмотреть файл

@ -618,6 +618,20 @@ _pixman_walk_composite_region (pixman_implementation_t *imp,
int32_t height,
pixman_composite_func_t composite_rect);
pixman_bool_t
_pixman_run_fast_path_scale (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 dest_x,
int32_t dest_y,
int32_t width,
int32_t height);
void
pixman_expand (uint64_t * dst,
const uint32_t * src,