зеркало из https://github.com/mozilla/gecko-dev.git
imported patch bug_552142_fast_scale_branch_pixman
This commit is contained in:
Родитель
1ca1cfe558
Коммит
3f254c5006
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче