mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
Added patch to improve performance of bilinear bitmap scaling.
This commit is contained in:
parent
3e2e449d4e
commit
12f8688fc5
@ -0,0 +1,29 @@
|
||||
From f7c317dac3581075e75168ce50c4523973422384 Mon Sep 17 00:00:00 2001
|
||||
From: Dmitry Timoshkov <dmitry@baikal.ru>
|
||||
Date: Sun, 5 Mar 2017 12:55:51 +0800
|
||||
Subject: gdiplus: Change the order of x/y loops in the scaler.
|
||||
|
||||
This improves performance by about 5%.
|
||||
---
|
||||
dlls/gdiplus/graphics.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
|
||||
index 142b68115e..02d699b00b 100644
|
||||
--- a/dlls/gdiplus/graphics.c
|
||||
+++ b/dlls/gdiplus/graphics.c
|
||||
@@ -3043,9 +3043,9 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
|
||||
y_dx = dst_to_src_points[2].X - dst_to_src_points[0].X;
|
||||
y_dy = dst_to_src_points[2].Y - dst_to_src_points[0].Y;
|
||||
|
||||
- for (x=dst_area.left; x<dst_area.right; x++)
|
||||
+ for (y=dst_area.top; y<dst_area.bottom; y++)
|
||||
{
|
||||
- for (y=dst_area.top; y<dst_area.bottom; y++)
|
||||
+ for (x=dst_area.left; x<dst_area.right; x++)
|
||||
{
|
||||
GpPointF src_pointf;
|
||||
ARGB *dst_color;
|
||||
--
|
||||
2.11.0
|
||||
|
@ -0,0 +1,65 @@
|
||||
From 04aee185cec481587e66fd410cf6ed2b6b6e2f90 Mon Sep 17 00:00:00 2001
|
||||
From: Dmitry Timoshkov <dmitry@baikal.ru>
|
||||
Date: Sun, 5 Mar 2017 13:07:43 +0800
|
||||
Subject: gdiplus: Change multiplications by additions in the x/y scaler loops.
|
||||
|
||||
This should imrove performance when floating point math will be replaced
|
||||
by fixed point calculations.
|
||||
---
|
||||
dlls/gdiplus/graphics.c | 18 ++++++++++++++++--
|
||||
1 file changed, 16 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
|
||||
index 02d699b00b..ef26887d14 100644
|
||||
--- a/dlls/gdiplus/graphics.c
|
||||
+++ b/dlls/gdiplus/graphics.c
|
||||
@@ -3026,6 +3026,8 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
|
||||
|
||||
if (do_resampling)
|
||||
{
|
||||
+ REAL delta_xx, delta_xy, delta_yx, delta_yy;
|
||||
+
|
||||
/* Transform the bits as needed to the destination. */
|
||||
dst_data = dst_dyn_data = heap_alloc_zero(sizeof(ARGB) * (dst_area.right - dst_area.left) * (dst_area.bottom - dst_area.top));
|
||||
if (!dst_data)
|
||||
@@ -3043,15 +3045,21 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
|
||||
y_dx = dst_to_src_points[2].X - dst_to_src_points[0].X;
|
||||
y_dy = dst_to_src_points[2].Y - dst_to_src_points[0].Y;
|
||||
|
||||
+ delta_yy = dst_area.top * y_dy;
|
||||
+ delta_yx = dst_area.top * y_dx;
|
||||
+
|
||||
for (y=dst_area.top; y<dst_area.bottom; y++)
|
||||
{
|
||||
+ delta_xx = dst_area.left * x_dx;
|
||||
+ delta_xy = dst_area.left * x_dy;
|
||||
+
|
||||
for (x=dst_area.left; x<dst_area.right; x++)
|
||||
{
|
||||
GpPointF src_pointf;
|
||||
ARGB *dst_color;
|
||||
|
||||
- src_pointf.X = dst_to_src_points[0].X + x * x_dx + y * y_dx;
|
||||
- src_pointf.Y = dst_to_src_points[0].Y + x * x_dy + y * y_dy;
|
||||
+ src_pointf.X = dst_to_src_points[0].X + delta_xx + delta_yx;
|
||||
+ src_pointf.Y = dst_to_src_points[0].Y + delta_xy + delta_yy;
|
||||
|
||||
dst_color = (ARGB*)(dst_data + dst_stride * (y - dst_area.top) + sizeof(ARGB) * (x - dst_area.left));
|
||||
|
||||
@@ -3060,7 +3068,13 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
|
||||
imageAttributes, interpolation, offset_mode);
|
||||
else
|
||||
*dst_color = 0;
|
||||
+
|
||||
+ delta_xx += x_dx;
|
||||
+ delta_yx += y_dx;
|
||||
}
|
||||
+
|
||||
+ delta_xy += x_dy;
|
||||
+ delta_yy += y_dy;
|
||||
}
|
||||
}
|
||||
else
|
||||
--
|
||||
2.11.0
|
||||
|
@ -0,0 +1,57 @@
|
||||
From f1b82c151d064eeafe234cdd95a4b29d7000232a Mon Sep 17 00:00:00 2001
|
||||
From: Dmitry Timoshkov <dmitry@baikal.ru>
|
||||
Date: Sun, 5 Mar 2017 13:18:21 +0800
|
||||
Subject: gdiplus: Remove ceilf/floorf calls from bilinear scaler. (v2)
|
||||
|
||||
This improves performance by about 55%.
|
||||
---
|
||||
dlls/gdiplus/graphics.c | 19 ++++++++++++-------
|
||||
1 file changed, 12 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
|
||||
index ef26887d14..58cfebb923 100644
|
||||
--- a/dlls/gdiplus/graphics.c
|
||||
+++ b/dlls/gdiplus/graphics.c
|
||||
@@ -526,7 +526,7 @@ static ARGB blend_colors(ARGB start, ARGB end, REAL position)
|
||||
INT start_a, end_a, final_a;
|
||||
INT pos;
|
||||
|
||||
- pos = gdip_round(position * 0xff);
|
||||
+ pos = (INT)(position * 255.0f + 0.5f);
|
||||
|
||||
start_a = ((start >> 24) & 0xff) * (pos ^ 0xff);
|
||||
end_a = ((end >> 24) & 0xff) * pos;
|
||||
@@ -928,6 +928,11 @@ static ARGB sample_bitmap_pixel(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT wi
|
||||
return ((DWORD*)(bits))[(x - src_rect->X) + (y - src_rect->Y) * src_rect->Width];
|
||||
}
|
||||
|
||||
+static FORCEINLINE int positive_ceilf(float f)
|
||||
+{
|
||||
+ return f - (int)f > 0.0f ? f + 1.0f : f;
|
||||
+}
|
||||
+
|
||||
static ARGB resample_bitmap_pixel(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT width,
|
||||
UINT height, GpPointF *point, GDIPCONST GpImageAttributes *attributes,
|
||||
InterpolationMode interpolation, PixelOffsetMode offset_mode)
|
||||
@@ -948,12 +953,12 @@ static ARGB resample_bitmap_pixel(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT
|
||||
ARGB top, bottom;
|
||||
float x_offset;
|
||||
|
||||
- leftxf = floorf(point->X);
|
||||
- leftx = (INT)leftxf;
|
||||
- rightx = (INT)ceilf(point->X);
|
||||
- topyf = floorf(point->Y);
|
||||
- topy = (INT)topyf;
|
||||
- bottomy = (INT)ceilf(point->Y);
|
||||
+ leftx = (INT)point->X;
|
||||
+ leftxf = (REAL)leftx;
|
||||
+ rightx = positive_ceilf(point->X);
|
||||
+ topy = (INT)point->Y;
|
||||
+ topyf = (REAL)topy;
|
||||
+ bottomy = positive_ceilf(point->Y);
|
||||
|
||||
if (leftx == rightx && topy == bottomy)
|
||||
return sample_bitmap_pixel(src_rect, bits, width, height,
|
||||
--
|
||||
2.11.0
|
||||
|
@ -0,0 +1,140 @@
|
||||
From 37b9499d8da295cd8819d85e9a563629ef13f22e Mon Sep 17 00:00:00 2001
|
||||
From: Dmitry Timoshkov <dmitry@baikal.ru>
|
||||
Date: Sun, 5 Mar 2017 14:34:51 +0800
|
||||
Subject: gdiplus: Prefer using pre-multiplied ARGB data in the scaler.
|
||||
|
||||
This further improves performance by about 20%.
|
||||
---
|
||||
dlls/gdiplus/graphics.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 91 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
|
||||
index 58cfebb923..bdee2e8318 100644
|
||||
--- a/dlls/gdiplus/graphics.c
|
||||
+++ b/dlls/gdiplus/graphics.c
|
||||
@@ -521,6 +521,17 @@ static GpStatus alpha_blend_pixels(GpGraphics *graphics, INT dst_x, INT dst_y,
|
||||
return alpha_blend_pixels_hrgn(graphics, dst_x, dst_y, src, src_width, src_height, src_stride, NULL, fmt);
|
||||
}
|
||||
|
||||
+/* NOTE: start and end pixels must be in pre-multiplied ARGB format */
|
||||
+static FORCEINLINE ARGB blend_colors_premult(ARGB start, ARGB end, REAL position)
|
||||
+{
|
||||
+ UINT pos = position * 255.0f + 0.5f;
|
||||
+ return
|
||||
+ (((((start >> 24) ) << 8) + (((end >> 24) ) - ((start >> 24) )) * pos) >> 8) << 24 |
|
||||
+ (((((start >> 16) & 0xff) << 8) + (((end >> 16) & 0xff) - ((start >> 16) & 0xff)) * pos) >> 8) << 16 |
|
||||
+ (((((start >> 8) & 0xff) << 8) + (((end >> 8) & 0xff) - ((start >> 8) & 0xff)) * pos) >> 8) << 8 |
|
||||
+ (((((start ) & 0xff) << 8) + (((end ) & 0xff) - ((start ) & 0xff)) * pos) >> 8);
|
||||
+}
|
||||
+
|
||||
static ARGB blend_colors(ARGB start, ARGB end, REAL position)
|
||||
{
|
||||
INT start_a, end_a, final_a;
|
||||
@@ -1002,6 +1013,75 @@ static ARGB resample_bitmap_pixel(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT
|
||||
}
|
||||
}
|
||||
|
||||
+static ARGB resample_bitmap_pixel_premult(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT width,
|
||||
+ UINT height, GpPointF *point, GDIPCONST GpImageAttributes *attributes,
|
||||
+ InterpolationMode interpolation, PixelOffsetMode offset_mode)
|
||||
+{
|
||||
+ static int fixme;
|
||||
+
|
||||
+ switch (interpolation)
|
||||
+ {
|
||||
+ default:
|
||||
+ if (!fixme++)
|
||||
+ FIXME("Unimplemented interpolation %i\n", interpolation);
|
||||
+ /* fall-through */
|
||||
+ case InterpolationModeBilinear:
|
||||
+ {
|
||||
+ REAL leftxf, topyf;
|
||||
+ INT leftx, rightx, topy, bottomy;
|
||||
+ ARGB topleft, topright, bottomleft, bottomright;
|
||||
+ ARGB top, bottom;
|
||||
+ float x_offset;
|
||||
+
|
||||
+ leftx = (INT)point->X;
|
||||
+ leftxf = (REAL)leftx;
|
||||
+ rightx = positive_ceilf(point->X);
|
||||
+ topy = (INT)point->Y;
|
||||
+ topyf = (REAL)topy;
|
||||
+ bottomy = positive_ceilf(point->Y);
|
||||
+
|
||||
+ if (leftx == rightx && topy == bottomy)
|
||||
+ return sample_bitmap_pixel(src_rect, bits, width, height,
|
||||
+ leftx, topy, attributes);
|
||||
+
|
||||
+ topleft = sample_bitmap_pixel(src_rect, bits, width, height,
|
||||
+ leftx, topy, attributes);
|
||||
+ topright = sample_bitmap_pixel(src_rect, bits, width, height,
|
||||
+ rightx, topy, attributes);
|
||||
+ bottomleft = sample_bitmap_pixel(src_rect, bits, width, height,
|
||||
+ leftx, bottomy, attributes);
|
||||
+ bottomright = sample_bitmap_pixel(src_rect, bits, width, height,
|
||||
+ rightx, bottomy, attributes);
|
||||
+
|
||||
+ x_offset = point->X - leftxf;
|
||||
+ top = blend_colors_premult(topleft, topright, x_offset);
|
||||
+ bottom = blend_colors_premult(bottomleft, bottomright, x_offset);
|
||||
+
|
||||
+ return blend_colors_premult(top, bottom, point->Y - topyf);
|
||||
+ }
|
||||
+ case InterpolationModeNearestNeighbor:
|
||||
+ {
|
||||
+ FLOAT pixel_offset;
|
||||
+ switch (offset_mode)
|
||||
+ {
|
||||
+ default:
|
||||
+ case PixelOffsetModeNone:
|
||||
+ case PixelOffsetModeHighSpeed:
|
||||
+ pixel_offset = 0.5;
|
||||
+ break;
|
||||
+
|
||||
+ case PixelOffsetModeHalf:
|
||||
+ case PixelOffsetModeHighQuality:
|
||||
+ pixel_offset = 0.0;
|
||||
+ break;
|
||||
+ }
|
||||
+ return sample_bitmap_pixel(src_rect, bits, width, height,
|
||||
+ floorf(point->X + pixel_offset), point->Y + pixel_offset, attributes);
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static REAL intersect_line_scanline(const GpPointF *p1, const GpPointF *p2, REAL y)
|
||||
{
|
||||
return (p1->X - p2->X) * (p2->Y - y) / (p2->Y - p1->Y) + p2->X;
|
||||
@@ -3010,8 +3090,10 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
|
||||
lockeddata.Scan0 = src_data;
|
||||
if (!do_resampling && bitmap->format == PixelFormat32bppPARGB)
|
||||
lockeddata.PixelFormat = apply_image_attributes(imageAttributes, NULL, 0, 0, 0, ColorAdjustTypeBitmap, bitmap->format);
|
||||
- else
|
||||
+ else if (imageAttributes != &defaultImageAttributes)
|
||||
lockeddata.PixelFormat = PixelFormat32bppARGB;
|
||||
+ else
|
||||
+ lockeddata.PixelFormat = PixelFormat32bppPARGB;
|
||||
|
||||
stat = GdipBitmapLockBits(bitmap, &src_area, ImageLockModeRead|ImageLockModeUserInputBuf,
|
||||
lockeddata.PixelFormat, &lockeddata);
|
||||
@@ -3069,8 +3151,14 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
|
||||
dst_color = (ARGB*)(dst_data + dst_stride * (y - dst_area.top) + sizeof(ARGB) * (x - dst_area.left));
|
||||
|
||||
if (src_pointf.X >= srcx && src_pointf.X < srcx + srcwidth && src_pointf.Y >= srcy && src_pointf.Y < srcy+srcheight)
|
||||
- *dst_color = resample_bitmap_pixel(&src_area, src_data, bitmap->width, bitmap->height, &src_pointf,
|
||||
- imageAttributes, interpolation, offset_mode);
|
||||
+ {
|
||||
+ if (lockeddata.PixelFormat != PixelFormat32bppPARGB)
|
||||
+ *dst_color = resample_bitmap_pixel(&src_area, src_data, bitmap->width, bitmap->height, &src_pointf,
|
||||
+ imageAttributes, interpolation, offset_mode);
|
||||
+ else
|
||||
+ *dst_color = resample_bitmap_pixel_premult(&src_area, src_data, bitmap->width, bitmap->height, &src_pointf,
|
||||
+ imageAttributes, interpolation, offset_mode);
|
||||
+ }
|
||||
else
|
||||
*dst_color = 0;
|
||||
|
||||
--
|
||||
2.11.0
|
||||
|
1
patches/gdiplus-Performance-Improvements/definition
Normal file
1
patches/gdiplus-Performance-Improvements/definition
Normal file
@ -0,0 +1 @@
|
||||
Fixes: Improve performance of bilinear bitmap scaling
|
@ -163,6 +163,7 @@ patch_enable_all ()
|
||||
enable_gdi32_Symbol_Truetype_Font="$1"
|
||||
enable_gdiplus_DC_Handling="$1"
|
||||
enable_gdiplus_Grayscale_PNG="$1"
|
||||
enable_gdiplus_Performance_Improvements="$1"
|
||||
enable_hal_KeQueryPerformanceCounter="$1"
|
||||
enable_hnetcfg_INetFwAuthorizedApplication="$1"
|
||||
enable_ieframe_IViewObject_Draw="$1"
|
||||
@ -713,6 +714,9 @@ patch_enable ()
|
||||
gdiplus-Grayscale_PNG)
|
||||
enable_gdiplus_Grayscale_PNG="$2"
|
||||
;;
|
||||
gdiplus-Performance-Improvements)
|
||||
enable_gdiplus_Performance_Improvements="$2"
|
||||
;;
|
||||
hal-KeQueryPerformanceCounter)
|
||||
enable_hal_KeQueryPerformanceCounter="$2"
|
||||
;;
|
||||
@ -4202,6 +4206,24 @@ if test "$enable_gdiplus_Grayscale_PNG" -eq 1; then
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset gdiplus-Performance-Improvements
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/gdiplus/graphics.c
|
||||
# |
|
||||
if test "$enable_gdiplus_Performance_Improvements" -eq 1; then
|
||||
patch_apply gdiplus-Performance-Improvements/0001-gdiplus-Change-the-order-of-x-y-loops-in-the-scaler.patch
|
||||
patch_apply gdiplus-Performance-Improvements/0002-gdiplus-Change-multiplications-by-additions-in-the-x.patch
|
||||
patch_apply gdiplus-Performance-Improvements/0003-gdiplus-Remove-ceilf-floorf-calls-from-bilinear-scal.patch
|
||||
patch_apply gdiplus-Performance-Improvements/0004-gdiplus-Prefer-using-pre-multiplied-ARGB-data-in-the.patch
|
||||
(
|
||||
printf '%s\n' '+ { "Dmitry Timoshkov", "gdiplus: Change the order of x/y loops in the scaler.", 1 },';
|
||||
printf '%s\n' '+ { "Dmitry Timoshkov", "gdiplus: Change multiplications by additions in the x/y scaler loops.", 1 },';
|
||||
printf '%s\n' '+ { "Dmitry Timoshkov", "gdiplus: Remove ceilf/floorf calls from bilinear scaler.", 2 },';
|
||||
printf '%s\n' '+ { "Dmitry Timoshkov", "gdiplus: Prefer using pre-multiplied ARGB data in the scaler.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset hal-KeQueryPerformanceCounter
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
|
Loading…
Reference in New Issue
Block a user