[Pixman] [PATCH] pixman: Use maximum precision for pixman-bits-image
Maarten Lankhorst
maarten.lankhorst at linux.intel.com
Fri Dec 7 10:55:49 UTC 2018
Op 06-12-2018 om 15:46 schreef Maarten Lankhorst:
> Op 06-12-2018 om 12:03 schreef Maarten Lankhorst:
>> Op 05-12-2018 om 11:24 schreef Basile Clement:
>>> Hi,
>>>
>>> On 12/5/18 9:08 AM, Pekka Paalanen wrote:
>>>> On Tue, 4 Dec 2018 17:36:18 +0100
>>>> Maarten Lankhorst <maarten.lankhorst at linux.intel.com> wrote:
>>>>> Series looks sane, 1/4 is cleaner than my version. I would change Bpp
>>>>> to cpp, or multiply by 8, since Bpp usually means bits per pixel.
>>>> And cpp means channels-per-pixel?
>>>>
>>>> B usually means bytes, b often means bits. But not always, so you can
>>>> never assume.
>>>>
>>>> I'd just write out bits_per_pixel or bytes_per_pixel, just like
>>>> pitch_bytes or stride_pixels or stride_uint32s or whatever makes it
>>>> totally obvious.
>>> This was indeed Bpp as in Bytes-per-pixel; I reused the variable name from pixman-general.c. Happy to change it to the more explicit bytes_per_pixel.
>>>
>>> On 12/4/18 5:36 PM, Maarten Lankhorst wrote:
>>>> Do you happen to have a patch to fix pixman-bits-image.c falling back to 8-bit paths as well?
>>> Are you referring to the fact that `get_scanline_float` gets data through `get_scanline_32` first? If so, I have not -- I understand this is only an issue with floating point formats, which were added after I wrote the patches.
>> This is also an issue with any format with >8 bpp, see PIXMAN_FORMAT_IS_WIDE(). This also affects the 8-bit sRGB format, and PIXMAN_x2r10g10b10 and its variations.
>>
>> ~Maarten
>>
>> _______________________________________________
>> Pixman mailing list
>> Pixman at lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/pixman
> Looks easier to add than expected. I've mostly completed my commit that does the same for pixman-bits-image, but might conflict with this series..
>
> _______________________________________________
> Pixman mailing list
> Pixman at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/pixman
Signed-off-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
---
pixman/pixman-bits-image.c | 478 ++++++++++++++++++++++++++++++-------
pixman/pixman-inlines.h | 25 ++
2 files changed, 418 insertions(+), 85 deletions(-)
diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 9fb91ff5831d..cb1c5ce12d46 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -36,43 +36,45 @@
#include "pixman-combine32.h"
#include "pixman-inlines.h"
-static uint32_t *
-_pixman_image_get_scanline_generic_float (pixman_iter_t * iter,
- const uint32_t *mask)
-{
- pixman_iter_get_scanline_t fetch_32 = iter->data;
- uint32_t *buffer = iter->buffer;
-
- fetch_32 (iter, NULL);
+/* Fetch functions */
- pixman_expand_to_float ((argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
+static force_inline void
+fetch_pixel_no_alpha_32 (bits_image_t *image,
+ int x, int y, pixman_bool_t check_bounds,
+ void *out)
+{
+ uint32_t *ret = out;
- return iter->buffer;
+ if (check_bounds &&
+ (x < 0 || x >= image->width || y < 0 || y >= image->height))
+ *ret = 0;
+ else
+ *ret = image->fetch_pixel_32 (image, x, y);
}
-/* Fetch functions */
-
-static force_inline uint32_t
-fetch_pixel_no_alpha (bits_image_t *image,
- int x, int y, pixman_bool_t check_bounds)
+static force_inline void
+fetch_pixel_no_alpha_float (bits_image_t *image,
+ int x, int y, pixman_bool_t check_bounds,
+ void *out)
{
+ argb_t *ret = out;
+
if (check_bounds &&
(x < 0 || x >= image->width || y < 0 || y >= image->height))
- {
- return 0;
- }
-
- return image->fetch_pixel_32 (image, x, y);
+ ret->a = ret->r = ret->g = ret->b = 0.f;
+ else
+ *ret = image->fetch_pixel_float (image, x, y);
}
-typedef uint32_t (* get_pixel_t) (bits_image_t *image,
- int x, int y, pixman_bool_t check_bounds);
+typedef void (* get_pixel_t) (bits_image_t *image,
+ int x, int y, pixman_bool_t check_bounds, void *out);
-static force_inline uint32_t
+static force_inline void
bits_image_fetch_pixel_nearest (bits_image_t *image,
pixman_fixed_t x,
pixman_fixed_t y,
- get_pixel_t get_pixel)
+ get_pixel_t get_pixel,
+ void *out)
{
int x0 = pixman_fixed_to_int (x - pixman_fixed_e);
int y0 = pixman_fixed_to_int (y - pixman_fixed_e);
@@ -82,19 +84,20 @@ bits_image_fetch_pixel_nearest (bits_image_t *image,
repeat (image->common.repeat, &x0, image->width);
repeat (image->common.repeat, &y0, image->height);
- return get_pixel (image, x0, y0, FALSE);
+ get_pixel (image, x0, y0, FALSE, out);
}
else
{
- return get_pixel (image, x0, y0, TRUE);
+ get_pixel (image, x0, y0, TRUE, out);
}
}
-static force_inline uint32_t
-bits_image_fetch_pixel_bilinear (bits_image_t *image,
- pixman_fixed_t x,
- pixman_fixed_t y,
- get_pixel_t get_pixel)
+static force_inline void
+bits_image_fetch_pixel_bilinear_32 (bits_image_t *image,
+ pixman_fixed_t x,
+ pixman_fixed_t y,
+ get_pixel_t get_pixel,
+ void *out)
{
pixman_repeat_t repeat_mode = image->common.repeat;
int width = image->width;
@@ -102,6 +105,7 @@ bits_image_fetch_pixel_bilinear (bits_image_t *image,
int x1, y1, x2, y2;
uint32_t tl, tr, bl, br;
int32_t distx, disty;
+ uint32_t *ret = out;
x1 = x - pixman_fixed_1 / 2;
y1 = y - pixman_fixed_1 / 2;
@@ -121,27 +125,77 @@ bits_image_fetch_pixel_bilinear (bits_image_t *image,
repeat (repeat_mode, &x2, width);
repeat (repeat_mode, &y2, height);
- tl = get_pixel (image, x1, y1, FALSE);
- bl = get_pixel (image, x1, y2, FALSE);
- tr = get_pixel (image, x2, y1, FALSE);
- br = get_pixel (image, x2, y2, FALSE);
+ get_pixel (image, x1, y1, FALSE, &tl);
+ get_pixel (image, x2, y1, FALSE, &tr);
+ get_pixel (image, x1, y2, FALSE, &bl);
+ get_pixel (image, x2, y2, FALSE, &br);
}
else
{
- tl = get_pixel (image, x1, y1, TRUE);
- tr = get_pixel (image, x2, y1, TRUE);
- bl = get_pixel (image, x1, y2, TRUE);
- br = get_pixel (image, x2, y2, TRUE);
+ get_pixel (image, x1, y1, TRUE, &tl);
+ get_pixel (image, x2, y1, TRUE, &tr);
+ get_pixel (image, x1, y2, TRUE, &bl);
+ get_pixel (image, x2, y2, TRUE, &br);
}
- return bilinear_interpolation (tl, tr, bl, br, distx, disty);
+ *ret = bilinear_interpolation (tl, tr, bl, br, distx, disty);
}
-static force_inline uint32_t
-bits_image_fetch_pixel_convolution (bits_image_t *image,
- pixman_fixed_t x,
- pixman_fixed_t y,
- get_pixel_t get_pixel)
+static force_inline void
+bits_image_fetch_pixel_bilinear_float (bits_image_t *image,
+ pixman_fixed_t x,
+ pixman_fixed_t y,
+ get_pixel_t get_pixel,
+ void *out)
+{
+ pixman_repeat_t repeat_mode = image->common.repeat;
+ int width = image->width;
+ int height = image->height;
+ int x1, y1, x2, y2;
+ argb_t tl, tr, bl, br;
+ float distx, disty;
+ argb_t *ret = out;
+
+ x1 = x - pixman_fixed_1 / 2;
+ y1 = y - pixman_fixed_1 / 2;
+
+ distx = ((float)pixman_fixed_fraction(x1)) / 65536.f;
+ disty = ((float)pixman_fixed_fraction(y1)) / 65536.f;
+
+ x1 = pixman_fixed_to_int (x1);
+ y1 = pixman_fixed_to_int (y1);
+ x2 = x1 + 1;
+ y2 = y1 + 1;
+
+ if (repeat_mode != PIXMAN_REPEAT_NONE)
+ {
+ repeat (repeat_mode, &x1, width);
+ repeat (repeat_mode, &y1, height);
+ repeat (repeat_mode, &x2, width);
+ repeat (repeat_mode, &y2, height);
+
+ get_pixel (image, x1, y1, FALSE, &tl);
+ get_pixel (image, x2, y1, FALSE, &tr);
+ get_pixel (image, x1, y2, FALSE, &bl);
+ get_pixel (image, x2, y2, FALSE, &br);
+ }
+ else
+ {
+ get_pixel (image, x1, y1, TRUE, &tl);
+ get_pixel (image, x2, y1, TRUE, &tr);
+ get_pixel (image, x1, y2, TRUE, &bl);
+ get_pixel (image, x2, y2, TRUE, &br);
+ }
+
+ *ret = bilinear_interpolation_float (tl, tr, bl, br, distx, disty);
+}
+
+static force_inline void
+bits_image_fetch_pixel_convolution_32 (bits_image_t *image,
+ pixman_fixed_t x,
+ pixman_fixed_t y,
+ get_pixel_t get_pixel,
+ void *out)
{
pixman_fixed_t *params = image->common.filter_params;
int x_off = (params[0] - pixman_fixed_1) >> 1;
@@ -153,6 +207,7 @@ bits_image_fetch_pixel_convolution (bits_image_t *image,
int width = image->width;
int height = image->height;
int srtot, sgtot, sbtot, satot;
+ uint32_t *ret = out;
params += 2;
@@ -181,11 +236,11 @@ bits_image_fetch_pixel_convolution (bits_image_t *image,
repeat (repeat_mode, &rx, width);
repeat (repeat_mode, &ry, height);
- pixel = get_pixel (image, rx, ry, FALSE);
+ get_pixel (image, rx, ry, FALSE, &pixel);
}
else
{
- pixel = get_pixel (image, rx, ry, TRUE);
+ get_pixel (image, rx, ry, TRUE, &pixel);
}
srtot += (int)RED_8 (pixel) * f;
@@ -208,14 +263,84 @@ bits_image_fetch_pixel_convolution (bits_image_t *image,
sgtot = CLIP (sgtot, 0, 0xff);
sbtot = CLIP (sbtot, 0, 0xff);
- return ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot));
+ *ret = ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot));
+}
+
+static force_inline void
+bits_image_fetch_pixel_convolution_float (bits_image_t *image,
+ pixman_fixed_t x,
+ pixman_fixed_t y,
+ get_pixel_t get_pixel,
+ void *out)
+{
+ pixman_fixed_t *params = image->common.filter_params;
+ int x_off = (params[0] - pixman_fixed_1) >> 1;
+ int y_off = (params[1] - pixman_fixed_1) >> 1;
+ int32_t cwidth = pixman_fixed_to_int (params[0]);
+ int32_t cheight = pixman_fixed_to_int (params[1]);
+ int32_t i, j, x1, x2, y1, y2;
+ pixman_repeat_t repeat_mode = image->common.repeat;
+ int width = image->width;
+ int height = image->height;
+ int srtot, sgtot, sbtot, satot;
+ argb_t *ret = out;
+
+ params += 2;
+
+ x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
+ y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
+ x2 = x1 + cwidth;
+ y2 = y1 + cheight;
+
+ srtot = sgtot = sbtot = satot = 0;
+
+ for (i = y1; i < y2; ++i)
+ {
+ for (j = x1; j < x2; ++j)
+ {
+ int rx = j;
+ int ry = i;
+
+ pixman_fixed_t f = *params;
+
+ if (f)
+ {
+ argb_t pixel;
+
+ if (repeat_mode != PIXMAN_REPEAT_NONE)
+ {
+ repeat (repeat_mode, &rx, width);
+ repeat (repeat_mode, &ry, height);
+
+ get_pixel (image, rx, ry, FALSE, &pixel);
+ }
+ else
+ {
+ get_pixel (image, rx, ry, TRUE, &pixel);
+ }
+
+ satot += pixel.a * f;
+ srtot += pixel.r * f;
+ sgtot += pixel.g * f;
+ sbtot += pixel.b * f;
+ }
+
+ params++;
+ }
+ }
+
+ ret->a = CLIP (satot / 65536.f, 0.f, 1.f);
+ ret->r = CLIP (srtot / 65536.f, 0.f, 1.f);
+ ret->g = CLIP (sgtot / 65536.f, 0.f, 1.f);
+ ret->b = CLIP (sbtot / 65536.f, 0.f, 1.f);
}
-static uint32_t
-bits_image_fetch_pixel_separable_convolution (bits_image_t *image,
- pixman_fixed_t x,
- pixman_fixed_t y,
- get_pixel_t get_pixel)
+static void
+bits_image_fetch_pixel_separable_convolution_32 (bits_image_t *image,
+ pixman_fixed_t x,
+ pixman_fixed_t y,
+ get_pixel_t get_pixel,
+ void *out)
{
pixman_fixed_t *params = image->common.filter_params;
pixman_repeat_t repeat_mode = image->common.repeat;
@@ -234,6 +359,7 @@ bits_image_fetch_pixel_separable_convolution (bits_image_t *image,
int32_t x1, x2, y1, y2;
int32_t px, py;
int i, j;
+ uint32_t *ret = out;
/* Round x and y to the middle of the closest phase before continuing. This
* ensures that the convolution matrix is aligned right, since it was
@@ -278,11 +404,11 @@ bits_image_fetch_pixel_separable_convolution (bits_image_t *image,
repeat (repeat_mode, &rx, width);
repeat (repeat_mode, &ry, height);
- pixel = get_pixel (image, rx, ry, FALSE);
+ get_pixel (image, rx, ry, FALSE, &pixel);
}
else
{
- pixel = get_pixel (image, rx, ry, TRUE);
+ get_pixel (image, rx, ry, TRUE, &pixel);
}
f = (fy * fx + 0x8000) >> 16;
@@ -306,46 +432,153 @@ bits_image_fetch_pixel_separable_convolution (bits_image_t *image,
sgtot = CLIP (sgtot, 0, 0xff);
sbtot = CLIP (sbtot, 0, 0xff);
- return ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot));
+ *ret = ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot));
}
-static force_inline uint32_t
-bits_image_fetch_pixel_filtered (bits_image_t *image,
+static void
+bits_image_fetch_pixel_separable_convolution_float (bits_image_t *image,
+ pixman_fixed_t x,
+ pixman_fixed_t y,
+ get_pixel_t get_pixel,
+ void *out)
+{
+ pixman_fixed_t *params = image->common.filter_params;
+ pixman_repeat_t repeat_mode = image->common.repeat;
+ int width = image->width;
+ int height = image->height;
+ int cwidth = pixman_fixed_to_int (params[0]);
+ int cheight = 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 x_phase_shift = 16 - x_phase_bits;
+ int y_phase_shift = 16 - y_phase_bits;
+ int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1;
+ int y_off = ((cheight << 16) - pixman_fixed_1) >> 1;
+ pixman_fixed_t *y_params;
+ int srtot, sgtot, sbtot, satot;
+ int32_t x1, x2, y1, y2;
+ int32_t px, py;
+ int i, j;
+ argb_t *ret = out;
+
+ /* Round x and y to the middle of the closest phase before continuing. This
+ * ensures that the convolution matrix is aligned right, since it was
+ * positioned relative to a particular phase (and not relative to whatever
+ * exact fraction we happen to get here).
+ */
+ x = ((x >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1);
+ y = ((y >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1);
+
+ px = (x & 0xffff) >> x_phase_shift;
+ py = (y & 0xffff) >> y_phase_shift;
+
+ y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight;
+
+ x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
+ y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
+ x2 = x1 + cwidth;
+ y2 = y1 + cheight;
+
+ srtot = sgtot = sbtot = satot = 0;
+
+ for (i = y1; i < y2; ++i)
+ {
+ pixman_fixed_48_16_t fy = *y_params++;
+ pixman_fixed_t *x_params = params + 4 + px * cwidth;
+
+ if (fy)
+ {
+ for (j = x1; j < x2; ++j)
+ {
+ pixman_fixed_t fx = *x_params++;
+ int rx = j;
+ int ry = i;
+
+ if (fx)
+ {
+ pixman_fixed_t f;
+ argb_t pixel;
+
+ if (repeat_mode != PIXMAN_REPEAT_NONE)
+ {
+ repeat (repeat_mode, &rx, width);
+ repeat (repeat_mode, &ry, height);
+
+ get_pixel (image, rx, ry, FALSE, &pixel);
+ }
+ else
+ {
+ get_pixel (image, rx, ry, TRUE, &pixel);
+ }
+
+ f = (fy * fx + 0x8000) >> 16;
+
+ satot += pixel.a * f;
+ srtot += pixel.r * f;
+ sgtot += pixel.g * f;
+ sbtot += pixel.b * f;
+ }
+ }
+ }
+ }
+
+ ret->a = CLIP (satot / 65536.f, 0.f, 1.f);
+ ret->r = CLIP (srtot / 65536.f, 0.f, 1.f);
+ ret->g = CLIP (sgtot / 65536.f, 0.f, 1.f);
+ ret->b = CLIP (sbtot / 65536.f, 0.f, 1.f);
+}
+
+static force_inline void
+bits_image_fetch_pixel_filtered (bits_image_t *image,
+ pixman_bool_t wide,
pixman_fixed_t x,
pixman_fixed_t y,
- get_pixel_t get_pixel)
+ get_pixel_t get_pixel,
+ void *out)
{
switch (image->common.filter)
{
case PIXMAN_FILTER_NEAREST:
case PIXMAN_FILTER_FAST:
- return bits_image_fetch_pixel_nearest (image, x, y, get_pixel);
+ bits_image_fetch_pixel_nearest (image, x, y, get_pixel, out);
break;
case PIXMAN_FILTER_BILINEAR:
case PIXMAN_FILTER_GOOD:
case PIXMAN_FILTER_BEST:
- return bits_image_fetch_pixel_bilinear (image, x, y, get_pixel);
+ if (wide)
+ bits_image_fetch_pixel_bilinear_float (image, x, y, get_pixel, out);
+ else
+ bits_image_fetch_pixel_bilinear_32 (image, x, y, get_pixel, out);
break;
case PIXMAN_FILTER_CONVOLUTION:
- return bits_image_fetch_pixel_convolution (image, x, y, get_pixel);
+ if (wide)
+ bits_image_fetch_pixel_convolution_float (image, x, y,
+ get_pixel, out);
+ else
+ bits_image_fetch_pixel_convolution_32 (image, x, y,
+ get_pixel, out);
break;
case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
- return bits_image_fetch_pixel_separable_convolution (image, x, y, get_pixel);
+ if (wide)
+ bits_image_fetch_pixel_separable_convolution_float (image, x, y,
+ get_pixel, out);
+ else
+ bits_image_fetch_pixel_separable_convolution_32 (image, x, y,
+ get_pixel, out);
break;
default:
break;
}
-
- return 0;
}
static uint32_t *
-bits_image_fetch_affine_no_alpha (pixman_iter_t * iter,
- const uint32_t * mask)
+__bits_image_fetch_affine_no_alpha (pixman_iter_t * iter,
+ pixman_bool_t wide,
+ const uint32_t * mask)
{
pixman_image_t *image = iter->image;
int offset = iter->x;
@@ -357,6 +590,8 @@ bits_image_fetch_affine_no_alpha (pixman_iter_t * iter,
pixman_fixed_t ux, uy;
pixman_vector_t v;
int i;
+ get_pixel_t get_pixel =
+ wide ? fetch_pixel_no_alpha_float : fetch_pixel_no_alpha_32;
/* reference point is the center of the pixel */
v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
@@ -384,27 +619,45 @@ bits_image_fetch_affine_no_alpha (pixman_iter_t * iter,
{
if (!mask || mask[i])
{
- buffer[i] = bits_image_fetch_pixel_filtered (
- &image->bits, x, y, fetch_pixel_no_alpha);
+ bits_image_fetch_pixel_filtered (
+ &image->bits, wide, x, y, get_pixel, buffer);
}
x += ux;
y += uy;
+ buffer += wide ? 4 : 1;
}
- return buffer;
+ return iter->buffer;
+}
+
+static uint32_t *
+bits_image_fetch_affine_no_alpha_32 (pixman_iter_t *iter,
+ const uint32_t *mask)
+{
+ return __bits_image_fetch_affine_no_alpha(iter, FALSE, mask);
+}
+
+static uint32_t *
+bits_image_fetch_affine_no_alpha_float (pixman_iter_t *iter,
+ const uint32_t *mask)
+{
+ return __bits_image_fetch_affine_no_alpha(iter, TRUE, mask);
}
/* General fetcher */
-static force_inline uint32_t
-fetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_bounds)
+static force_inline void
+fetch_pixel_general_32 (bits_image_t *image,
+ int x, int y, pixman_bool_t check_bounds,
+ void *out)
{
- uint32_t pixel;
+ uint32_t pixel, *ret = out;
if (check_bounds &&
(x < 0 || x >= image->width || y < 0 || y >= image->height))
{
- return 0;
+ *ret = 0;
+ return;
}
pixel = image->fetch_pixel_32 (image, x, y);
@@ -433,18 +686,59 @@ fetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_boun
pixel |= (pixel_a << 24);
}
- return pixel;
+ *ret = pixel;
+}
+
+static force_inline void
+fetch_pixel_general_float (bits_image_t *image,
+ int x, int y, pixman_bool_t check_bounds,
+ void *out)
+{
+ argb_t *ret = out;
+
+ if (check_bounds &&
+ (x < 0 || x >= image->width || y < 0 || y >= image->height))
+ {
+ ret->a = ret->r = ret->g = ret->b = 0;
+ return;
+ }
+
+ *ret = image->fetch_pixel_float (image, x, y);
+
+ if (image->common.alpha_map)
+ {
+ x -= image->common.alpha_origin_x;
+ y -= image->common.alpha_origin_y;
+
+ if (x < 0 || x >= image->common.alpha_map->width ||
+ y < 0 || y >= image->common.alpha_map->height)
+ {
+ ret->a = 0.f;
+ }
+ else
+ {
+ argb_t alpha;
+
+ alpha = image->common.alpha_map->fetch_pixel_float (
+ image->common.alpha_map, x, y);
+
+ ret->a = alpha.a;
+ }
+ }
}
static uint32_t *
-bits_image_fetch_general (pixman_iter_t *iter,
- const uint32_t *mask)
+__bits_image_fetch_general (pixman_iter_t *iter,
+ pixman_bool_t wide,
+ const uint32_t *mask)
{
pixman_image_t *image = iter->image;
int offset = iter->x;
int line = iter->y++;
int width = iter->width;
uint32_t * buffer = iter->buffer;
+ get_pixel_t get_pixel =
+ wide ? fetch_pixel_general_float : fetch_pixel_general_32;
pixman_fixed_t x, y, w;
pixman_fixed_t ux, uy, uw;
@@ -493,16 +787,31 @@ bits_image_fetch_general (pixman_iter_t *iter,
y0 = 0;
}
- buffer[i] = bits_image_fetch_pixel_filtered (
- &image->bits, x0, y0, fetch_pixel_general);
+ bits_image_fetch_pixel_filtered (
+ &image->bits, wide, x0, y0, get_pixel, buffer);
}
x += ux;
y += uy;
w += uw;
+ buffer += wide ? 4 : 1;
}
- return buffer;
+ return iter->buffer;
+}
+
+static uint32_t *
+bits_image_fetch_general_32 (pixman_iter_t *iter,
+ const uint32_t *mask)
+{
+ return __bits_image_fetch_general(iter, FALSE, mask);
+}
+
+static uint32_t *
+bits_image_fetch_general_float (pixman_iter_t *iter,
+ const uint32_t *mask)
+{
+ return __bits_image_fetch_general(iter, TRUE, mask);
}
static void
@@ -703,15 +1012,15 @@ static const fetcher_info_t fetcher_info[] =
/* Affine, no alpha */
{ PIXMAN_any,
(FAST_PATH_NO_ALPHA_MAP | FAST_PATH_HAS_TRANSFORM | FAST_PATH_AFFINE_TRANSFORM),
- bits_image_fetch_affine_no_alpha,
- _pixman_image_get_scanline_generic_float
+ bits_image_fetch_affine_no_alpha_32,
+ bits_image_fetch_affine_no_alpha_float,
},
/* General */
{ PIXMAN_any,
0,
- bits_image_fetch_general,
- _pixman_image_get_scanline_generic_float
+ bits_image_fetch_general_32,
+ bits_image_fetch_general_float,
},
{ PIXMAN_null },
@@ -741,7 +1050,6 @@ _pixman_bits_image_src_iter_init (pixman_image_t *image, pixman_iter_t *iter)
}
else
{
- iter->data = info->get_scanline_32;
iter->get_scanline = info->get_scanline_float;
}
return;
diff --git a/pixman/pixman-inlines.h b/pixman/pixman-inlines.h
index 1c8441d6dabe..332e208140a0 100644
--- a/pixman/pixman-inlines.h
+++ b/pixman/pixman-inlines.h
@@ -222,6 +222,31 @@ bilinear_interpolation (uint32_t tl, uint32_t tr,
#endif
#endif // BILINEAR_INTERPOLATION_BITS <= 4
+static force_inline argb_t
+bilinear_interpolation_float (argb_t tl, argb_t tr,
+ argb_t bl, argb_t br,
+ float distx, float disty)
+{
+ float distxy, distxiy, distixy, distixiy;
+ argb_t r;
+
+ distxy = distx * disty;
+ distxiy = distx - (1.f - distxy);
+ distixy = (1.f - distx) * disty;
+ distixiy = (1.f - distx) * (1.f - disty);
+
+ r.a = tl.a * distixiy + tr.a * distxiy +
+ bl.a * distixy + br.a * distxy;
+ r.r = tl.r * distixiy + tr.r * distxiy +
+ bl.r * distixy + br.r * distxy;
+ r.g = tl.g * distixiy + tr.g * distxiy +
+ bl.g * distixy + br.g * distxy;
+ r.b = tl.b * distixiy + tr.b * distxiy +
+ bl.b * distixy + br.b * distxy;
+
+ return r;
+}
+
/*
* For each scanline fetched from source image with PAD repeat:
* - calculate how many pixels need to be padded on the left side
--
2.19.2
More information about the Pixman
mailing list