winehq.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2025
February
January
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
July
June
May
April
March
February
January
2007
December
November
October
September
August
July
June
May
April
March
February
January
2006
December
November
October
September
August
July
June
May
April
March
February
January
2005
December
November
October
September
August
July
June
May
April
March
February
January
2004
December
November
October
September
August
July
June
May
April
March
February
January
2003
December
November
October
September
August
July
June
May
April
March
February
January
2002
December
November
October
September
August
July
June
May
April
March
February
January
2001
December
November
October
September
August
July
June
May
April
March
February
List overview
wine-commits
July 2020
----- 2025 -----
February 2025
January 2025
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
May 2005
April 2005
March 2005
February 2005
January 2005
----- 2004 -----
December 2004
November 2004
October 2004
September 2004
August 2004
July 2004
June 2004
May 2004
April 2004
March 2004
February 2004
January 2004
----- 2003 -----
December 2003
November 2003
October 2003
September 2003
August 2003
July 2003
June 2003
May 2003
April 2003
March 2003
February 2003
January 2003
----- 2002 -----
December 2002
November 2002
October 2002
September 2002
August 2002
July 2002
June 2002
May 2002
April 2002
March 2002
February 2002
January 2002
----- 2001 -----
December 2001
November 2001
October 2001
September 2001
August 2001
July 2001
June 2001
May 2001
April 2001
March 2001
February 2001
wine-commits@winehq.org
1 participants
826 discussions
Start a n
N
ew thread
Shawn M. Chapla : gdiplus: Use FromRect constructor in LinearGradientBrush deserialization.
by Alexandre Julliard
24 Jul '20
24 Jul '20
Module: wine Branch: master Commit: d3de57c2b3f82c0f660af11571bcdf1747d39202 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=d3de57c2b3f82c0f660af115…
Author: Shawn M. Chapla <schapla(a)codeweavers.com> Date: Wed Jul 22 23:08:12 2020 -0400 gdiplus: Use FromRect constructor in LinearGradientBrush deserialization. Signed-off-by: Shawn M. Chapla <schapla(a)codeweavers.com> Signed-off-by: Esme Povirk <esme(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/gdiplus/metafile.c | 15 ++++++++------- dlls/gdiplus/tests/metafile.c | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c index 7f019749ea..e0ff6cae7a 100644 --- a/dlls/gdiplus/metafile.c +++ b/dlls/gdiplus/metafile.c @@ -2202,7 +2202,7 @@ static GpStatus metafile_deserialize_brush(const BYTE *record_data, UINT data_si case BrushTypeLinearGradient: { GpLineGradient *gradient = NULL; - GpPointF startpoint, endpoint; + GpRectF rect; UINT position_count = 0; offset = header_size + FIELD_OFFSET(EmfPlusLinearGradientBrushData, OptionalData); @@ -2240,13 +2240,14 @@ static GpStatus metafile_deserialize_brush(const BYTE *record_data, UINT data_si return InvalidParameter; } - startpoint.X = data->BrushData.lineargradient.RectF.X; - startpoint.Y = data->BrushData.lineargradient.RectF.Y; - endpoint.X = startpoint.X + data->BrushData.lineargradient.RectF.Width; - endpoint.Y = startpoint.Y + data->BrushData.lineargradient.RectF.Height; + rect.X = data->BrushData.lineargradient.RectF.X; + rect.Y = data->BrushData.lineargradient.RectF.Y; + rect.Width = data->BrushData.lineargradient.RectF.Width; + rect.Height = data->BrushData.lineargradient.RectF.Height; - status = GdipCreateLineBrush(&startpoint, &endpoint, data->BrushData.lineargradient.StartColor, - data->BrushData.lineargradient.EndColor, data->BrushData.lineargradient.WrapMode, &gradient); + status = GdipCreateLineBrushFromRect(&rect, data->BrushData.lineargradient.StartColor, + data->BrushData.lineargradient.EndColor, LinearGradientModeHorizontal, + data->BrushData.lineargradient.WrapMode, &gradient); if (status == Ok) { if (transform) diff --git a/dlls/gdiplus/tests/metafile.c b/dlls/gdiplus/tests/metafile.c index cdc53b39a1..e2d5171f8a 100644 --- a/dlls/gdiplus/tests/metafile.c +++ b/dlls/gdiplus/tests/metafile.c @@ -3377,7 +3377,7 @@ static void test_lineargradient(void) stat = GdipBitmapGetPixel(bitmap, 18, 10, &color); expect(Ok, stat); - todo_wine expect(0xff990066, color); + expect(0xff990066, color); /* Verify vertical gradient fill. */ stat = GdipBitmapGetPixel(bitmap, 50, 10, &color); @@ -3395,7 +3395,7 @@ static void test_lineargradient(void) stat = GdipBitmapGetPixel(bitmap, 18, 50, &color); expect(Ok, stat); - todo_wine expect(0xff4700b8, color); + expect(0xff4700b8, color); /* Verify preset color gradient fill. */ stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
1
0
0
0
Shawn M. Chapla : gdiplus: Fix LinearGradientBrush deserialization off-by-one errors.
by Alexandre Julliard
24 Jul '20
24 Jul '20
Module: wine Branch: master Commit: 6c787852c4b484d9b7e230c87f0662fb9af2c541 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=6c787852c4b484d9b7e230c8…
Author: Shawn M. Chapla <schapla(a)codeweavers.com> Date: Wed Jul 22 23:08:11 2020 -0400 gdiplus: Fix LinearGradientBrush deserialization off-by-one errors. Signed-off-by: Shawn M. Chapla <schapla(a)codeweavers.com> Signed-off-by: Esme Povirk <esme(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/gdiplus/metafile.c | 4 ++-- dlls/gdiplus/tests/metafile.c | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c index ff21b8ed24..7f019749ea 100644 --- a/dlls/gdiplus/metafile.c +++ b/dlls/gdiplus/metafile.c @@ -2206,7 +2206,7 @@ static GpStatus metafile_deserialize_brush(const BYTE *record_data, UINT data_si UINT position_count = 0; offset = header_size + FIELD_OFFSET(EmfPlusLinearGradientBrushData, OptionalData); - if (data_size <= offset) + if (data_size < offset) return InvalidParameter; brushflags = data->BrushData.lineargradient.BrushDataFlags; @@ -2215,7 +2215,7 @@ static GpStatus metafile_deserialize_brush(const BYTE *record_data, UINT data_si if (brushflags & BrushDataTransform) { - if (data_size <= offset + sizeof(EmfPlusTransformMatrix)) + if (data_size < offset + sizeof(EmfPlusTransformMatrix)) return InvalidParameter; transform = (EmfPlusTransformMatrix *)(record_data + offset); offset += sizeof(EmfPlusTransformMatrix); diff --git a/dlls/gdiplus/tests/metafile.c b/dlls/gdiplus/tests/metafile.c index 29113fc3a0..cdc53b39a1 100644 --- a/dlls/gdiplus/tests/metafile.c +++ b/dlls/gdiplus/tests/metafile.c @@ -3273,10 +3273,10 @@ static void test_fillregion(void) static const emfplus_record lineargradient_records[] = { { EMR_HEADER }, { EmfPlusRecordTypeHeader }, - { EmfPlusRecordTypeObject, ObjectTypeBrush << 8, 0, 1 }, - { EmfPlusRecordTypeFillRects, 0x4000, 0, 1 }, - { EmfPlusRecordTypeObject, (ObjectTypeBrush << 8) | 1, 0, 1 }, - { EmfPlusRecordTypeFillRects, 0x4000, 0, 1 }, + { EmfPlusRecordTypeObject, ObjectTypeBrush << 8 }, + { EmfPlusRecordTypeFillRects, 0x4000 }, + { EmfPlusRecordTypeObject, (ObjectTypeBrush << 8) | 1 }, + { EmfPlusRecordTypeFillRects, 0x4000 }, { EmfPlusRecordTypeObject, (ObjectTypeBrush << 8) | 2 }, { EmfPlusRecordTypeFillRects, 0x4000 }, { EmfPlusRecordTypeObject, (ObjectTypeBrush << 8) | 3 }, @@ -3373,7 +3373,7 @@ static void test_lineargradient(void) /* Verify horizontal gradient fill. */ stat = GdipBitmapGetPixel(bitmap, 10, 10, &color); expect(Ok, stat); - todo_wine expect(0xffff0000, color); + expect(0xffff0000, color); stat = GdipBitmapGetPixel(bitmap, 18, 10, &color); expect(Ok, stat); @@ -3382,11 +3382,11 @@ static void test_lineargradient(void) /* Verify vertical gradient fill. */ stat = GdipBitmapGetPixel(bitmap, 50, 10, &color); expect(Ok, stat); - todo_wine expect(0xffff0000, color); + expect(0xffff0000, color); stat = GdipBitmapGetPixel(bitmap, 50, 18, &color); expect(Ok, stat); - todo_wine expect(0xff990066, color); + expect(0xff990066, color); /* Verify custom blend gradient fill. */ stat = GdipBitmapGetPixel(bitmap, 10, 50, &color);
1
0
0
0
Shawn M. Chapla : gdiplus: Add LinearGradient brush object serialization.
by Alexandre Julliard
24 Jul '20
24 Jul '20
Module: wine Branch: master Commit: 60fd827d8b461e80bb271fcbc6959515a7a7681a URL:
https://source.winehq.org/git/wine.git/?a=commit;h=60fd827d8b461e80bb271fcb…
Author: Shawn M. Chapla <schapla(a)codeweavers.com> Date: Wed Jul 22 23:08:10 2020 -0400 gdiplus: Add LinearGradient brush object serialization. Signed-off-by: Shawn M. Chapla <schapla(a)codeweavers.com> Signed-off-by: Esme Povirk <esme(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/gdiplus/metafile.c | 81 +++++++++++++++++++++++++++++++++++++++++++ dlls/gdiplus/tests/metafile.c | 30 ++++++++-------- 2 files changed, 96 insertions(+), 15 deletions(-) diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c index 1d7c0fe306..ff21b8ed24 100644 --- a/dlls/gdiplus/metafile.c +++ b/dlls/gdiplus/metafile.c @@ -1036,6 +1036,26 @@ static GpStatus METAFILE_PrepareBrushData(GDIPCONST GpBrush *brush, DWORD *size) case BrushTypeHatchFill: *size = FIELD_OFFSET(EmfPlusBrush, BrushData) + sizeof(EmfPlusHatchBrushData); break; + case BrushTypeLinearGradient: + { + BOOL ignore_xform; + GpLineGradient *gradient = (GpLineGradient*)brush; + + *size = FIELD_OFFSET(EmfPlusBrush, BrushData.lineargradient.OptionalData); + + GdipIsMatrixIdentity(&gradient->transform, &ignore_xform); + if (!ignore_xform) + *size += sizeof(gradient->transform); + + if (gradient->pblendcount > 1 && gradient->pblendcolor && gradient->pblendpos) + *size += sizeof(DWORD) + gradient->pblendcount * + (sizeof(*gradient->pblendcolor) + sizeof(*gradient->pblendpos)); + else if (gradient->blendcount > 1 && gradient->blendfac && gradient->blendpos) + *size += sizeof(DWORD) + gradient->blendcount * + (sizeof(*gradient->blendfac) + sizeof(*gradient->blendpos)); + + break; + } default: FIXME("unsupported brush type: %d\n", brush->bt); return NotImplemented; @@ -1065,6 +1085,67 @@ static void METAFILE_FillBrushData(GDIPCONST GpBrush *brush, EmfPlusBrush *data) data->BrushData.hatch.BackColor = hatch->backcol; break; } + case BrushTypeLinearGradient: + { + BYTE *cursor; + BOOL ignore_xform; + GpLineGradient *gradient = (GpLineGradient*)brush; + + data->BrushData.lineargradient.BrushDataFlags = 0; + data->BrushData.lineargradient.WrapMode = gradient->wrap; + data->BrushData.lineargradient.RectF.X = gradient->rect.X; + data->BrushData.lineargradient.RectF.Y = gradient->rect.Y; + data->BrushData.lineargradient.RectF.Width = gradient->rect.Width; + data->BrushData.lineargradient.RectF.Height = gradient->rect.Height; + data->BrushData.lineargradient.StartColor = gradient->startcolor; + data->BrushData.lineargradient.EndColor = gradient->endcolor; + data->BrushData.lineargradient.Reserved1 = gradient->startcolor; + data->BrushData.lineargradient.Reserved2 = gradient->endcolor; + + if (gradient->gamma) + data->BrushData.lineargradient.BrushDataFlags |= BrushDataIsGammaCorrected; + + cursor = &data->BrushData.lineargradient.OptionalData[0]; + + GdipIsMatrixIdentity(&gradient->transform, &ignore_xform); + if (!ignore_xform) + { + data->BrushData.lineargradient.BrushDataFlags |= BrushDataTransform; + memcpy(cursor, &gradient->transform, sizeof(gradient->transform)); + cursor += sizeof(gradient->transform); + } + + if (gradient->pblendcount > 1 && gradient->pblendcolor && gradient->pblendpos) + { + const DWORD count = gradient->pblendcount; + + data->BrushData.lineargradient.BrushDataFlags |= BrushDataPresetColors; + + memcpy(cursor, &count, sizeof(count)); + cursor += sizeof(count); + + memcpy(cursor, gradient->pblendpos, count * sizeof(*gradient->pblendpos)); + cursor += count * sizeof(*gradient->pblendpos); + + memcpy(cursor, gradient->pblendcolor, count * sizeof(*gradient->pblendcolor)); + } + else if (gradient->blendcount > 1 && gradient->blendfac && gradient->blendpos) + { + const DWORD count = gradient->blendcount; + + data->BrushData.lineargradient.BrushDataFlags |= BrushDataBlendFactorsH; + + memcpy(cursor, &count, sizeof(count)); + cursor += sizeof(count); + + memcpy(cursor, gradient->blendpos, count * sizeof(*gradient->blendpos)); + cursor += count * sizeof(*gradient->blendpos); + + memcpy(cursor, gradient->blendfac, count * sizeof(*gradient->blendfac)); + } + + break; + } default: FIXME("unsupported brush type: %d\n", brush->bt); } diff --git a/dlls/gdiplus/tests/metafile.c b/dlls/gdiplus/tests/metafile.c index bba44d15da..29113fc3a0 100644 --- a/dlls/gdiplus/tests/metafile.c +++ b/dlls/gdiplus/tests/metafile.c @@ -3273,14 +3273,14 @@ static void test_fillregion(void) static const emfplus_record lineargradient_records[] = { { EMR_HEADER }, { EmfPlusRecordTypeHeader }, - { EmfPlusRecordTypeObject, ObjectTypeBrush << 8, 1 }, - { EmfPlusRecordTypeFillRects, 0x4000, 1 }, - { EmfPlusRecordTypeObject, (ObjectTypeBrush << 8) | 1, 1 }, - { EmfPlusRecordTypeFillRects, 0x4000, 1 }, - { EmfPlusRecordTypeObject, (ObjectTypeBrush << 8) | 2, 1 }, - { EmfPlusRecordTypeFillRects, 0x4000, 1 }, - { EmfPlusRecordTypeObject, (ObjectTypeBrush << 8) | 3, 1 }, - { EmfPlusRecordTypeFillRects, 0x4000, 1 }, + { EmfPlusRecordTypeObject, ObjectTypeBrush << 8, 0, 1 }, + { EmfPlusRecordTypeFillRects, 0x4000, 0, 1 }, + { EmfPlusRecordTypeObject, (ObjectTypeBrush << 8) | 1, 0, 1 }, + { EmfPlusRecordTypeFillRects, 0x4000, 0, 1 }, + { EmfPlusRecordTypeObject, (ObjectTypeBrush << 8) | 2 }, + { EmfPlusRecordTypeFillRects, 0x4000 }, + { EmfPlusRecordTypeObject, (ObjectTypeBrush << 8) | 3 }, + { EmfPlusRecordTypeFillRects, 0x4000 }, { EmfPlusRecordTypeEndOfFile }, { EMR_EOF }, { 0 } @@ -3342,16 +3342,16 @@ static void test_lineargradient(void) expect(Ok, stat); stat = GdipFillRectangles(graphics, vertbrush, &vertrect, 1); - todo_wine expect(Ok, stat); + expect(Ok, stat); stat = GdipFillRectangles(graphics, horizbrush, &horizrect, 1); - todo_wine expect(Ok, stat); + expect(Ok, stat); stat = GdipFillRectangles(graphics, blendbrush, &blendrect, 1); - todo_wine expect(Ok, stat); + expect(Ok, stat); stat = GdipFillRectangles(graphics, presetbrush, &presetrect, 1); - todo_wine expect(Ok, stat); + expect(Ok, stat); stat = GdipDeleteGraphics(graphics); graphics = NULL; @@ -3391,7 +3391,7 @@ static void test_lineargradient(void) /* Verify custom blend gradient fill. */ stat = GdipBitmapGetPixel(bitmap, 10, 50, &color); expect(Ok, stat); - todo_wine expect(0xffff0000, color); + expect(0xffff0000, color); stat = GdipBitmapGetPixel(bitmap, 18, 50, &color); expect(Ok, stat); @@ -3400,11 +3400,11 @@ static void test_lineargradient(void) /* Verify preset color gradient fill. */ stat = GdipBitmapGetPixel(bitmap, 50, 50, &color); expect(Ok, stat); - todo_wine expect(0xffff0000, color); + expect(0xffff0000, color); stat = GdipBitmapGetPixel(bitmap, 50, 60, &color); expect(Ok, stat); - todo_wine expect(0xff00ff00, color); + expect(0xff00ff00, color); GdipDeleteBrush(vertbrush); GdipDeleteBrush(horizbrush);
1
0
0
0
Shawn M. Chapla : gdiplus/tests: Add metafile LinearGradient brush test.
by Alexandre Julliard
24 Jul '20
24 Jul '20
Module: wine Branch: master Commit: 6c57cf5eee74ecaef9d654380c34ea9ba3850cdc URL:
https://source.winehq.org/git/wine.git/?a=commit;h=6c57cf5eee74ecaef9d65438…
Author: Shawn M. Chapla <schapla(a)codeweavers.com> Date: Wed Jul 22 23:08:09 2020 -0400 gdiplus/tests: Add metafile LinearGradient brush test. Signed-off-by: Shawn M. Chapla <schapla(a)codeweavers.com> Signed-off-by: Esme Povirk <esme(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/gdiplus/tests/metafile.c | 146 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) diff --git a/dlls/gdiplus/tests/metafile.c b/dlls/gdiplus/tests/metafile.c index ddb58504c9..bba44d15da 100644 --- a/dlls/gdiplus/tests/metafile.c +++ b/dlls/gdiplus/tests/metafile.c @@ -3270,6 +3270,151 @@ static void test_fillregion(void) GdipDisposeImage((GpImage*)metafile); } +static const emfplus_record lineargradient_records[] = { + { EMR_HEADER }, + { EmfPlusRecordTypeHeader }, + { EmfPlusRecordTypeObject, ObjectTypeBrush << 8, 1 }, + { EmfPlusRecordTypeFillRects, 0x4000, 1 }, + { EmfPlusRecordTypeObject, (ObjectTypeBrush << 8) | 1, 1 }, + { EmfPlusRecordTypeFillRects, 0x4000, 1 }, + { EmfPlusRecordTypeObject, (ObjectTypeBrush << 8) | 2, 1 }, + { EmfPlusRecordTypeFillRects, 0x4000, 1 }, + { EmfPlusRecordTypeObject, (ObjectTypeBrush << 8) | 3, 1 }, + { EmfPlusRecordTypeFillRects, 0x4000, 1 }, + { EmfPlusRecordTypeEndOfFile }, + { EMR_EOF }, + { 0 } +}; + +static void test_lineargradient(void) +{ + static const GpPointF dst_points[3] = {{0.0, 0.0}, {100.0, 0.0}, {0.0, 100.0}}; + static const GpRectF frame = {0.0, 0.0, 100.0, 100.0}; + static const GpRectF horizrect = {10.0, 10.0, 20.0, 20.0}; + static const GpRectF vertrect = {50.0, 10.0, 20.0, 20.0}; + static const GpRectF blendrect = {10.0, 50.0, 20.0, 20.0}; + static const GpRectF presetrect = {50.0, 50.0, 20.0, 20.0}; + static const REAL blendfac[3] = {0.0, 0.9, 1.0}; + static const REAL blendpos[3] = {0.0, 0.5, 1.0}; + static const ARGB pblendcolor[3] = {0xffff0000, 0xff00ff00, 0xff0000ff}; + static const REAL pblendpos[3] = {0.0, 0.5, 1.0}; + + ARGB color; + GpBitmap *bitmap; + GpBrush *horizbrush, *vertbrush, *blendbrush, *presetbrush; + GpGraphics *graphics; + GpMetafile *metafile; + GpStatus stat; + HDC hdc; + + hdc = CreateCompatibleDC(0); + stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, + L"winetest", &metafile); + expect(Ok, stat); + DeleteDC(hdc); + hdc = NULL; + + stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics); + expect(Ok, stat); + + /* Test various brush types to cover all valid combinations + of optional serialized data. */ + stat = GdipCreateLineBrushFromRect(&horizrect, 0xffff0000, 0xff0000ff, + LinearGradientModeHorizontal, WrapModeTile, (GpLineGradient**)&horizbrush); + expect(Ok, stat); + + stat = GdipCreateLineBrushFromRect(&vertrect, 0xffff0000, 0xff0000ff, + LinearGradientModeVertical, WrapModeTile, (GpLineGradient**)&vertbrush); + expect(Ok, stat); + + stat = GdipCreateLineBrushFromRect(&blendrect, 0xffff0000, 0xff0000ff, + LinearGradientModeHorizontal, WrapModeTile, (GpLineGradient**)&blendbrush); + expect(Ok, stat); + + stat = GdipSetLineBlend((GpLineGradient*)blendbrush, blendfac, blendpos, 3); + expect(Ok, stat); + + stat = GdipCreateLineBrushFromRect(&presetrect, 0xffff0000, 0xff0000ff, + LinearGradientModeVertical, WrapModeTile, (GpLineGradient**)&presetbrush); + expect(Ok, stat); + + stat = GdipSetLinePresetBlend((GpLineGradient*)presetbrush, pblendcolor, pblendpos, 3); + expect(Ok, stat); + + stat = GdipFillRectangles(graphics, vertbrush, &vertrect, 1); + todo_wine expect(Ok, stat); + + stat = GdipFillRectangles(graphics, horizbrush, &horizrect, 1); + todo_wine expect(Ok, stat); + + stat = GdipFillRectangles(graphics, blendbrush, &blendrect, 1); + todo_wine expect(Ok, stat); + + stat = GdipFillRectangles(graphics, presetbrush, &presetrect, 1); + todo_wine expect(Ok, stat); + + stat = GdipDeleteGraphics(graphics); + graphics = NULL; + expect(Ok, stat); + + check_metafile(metafile, lineargradient_records, "lineargradient metafile", dst_points, + &frame, UnitPixel); + sync_metafile(&metafile, "lineargradient.emf"); + + stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap); + expect(Ok, stat); + + stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics); + expect(Ok, stat); + + play_metafile(metafile, graphics, lineargradient_records, "lineargradient playback", + dst_points, &frame, UnitPixel); + + /* Verify horizontal gradient fill. */ + stat = GdipBitmapGetPixel(bitmap, 10, 10, &color); + expect(Ok, stat); + todo_wine expect(0xffff0000, color); + + stat = GdipBitmapGetPixel(bitmap, 18, 10, &color); + expect(Ok, stat); + todo_wine expect(0xff990066, color); + + /* Verify vertical gradient fill. */ + stat = GdipBitmapGetPixel(bitmap, 50, 10, &color); + expect(Ok, stat); + todo_wine expect(0xffff0000, color); + + stat = GdipBitmapGetPixel(bitmap, 50, 18, &color); + expect(Ok, stat); + todo_wine expect(0xff990066, color); + + /* Verify custom blend gradient fill. */ + stat = GdipBitmapGetPixel(bitmap, 10, 50, &color); + expect(Ok, stat); + todo_wine expect(0xffff0000, color); + + stat = GdipBitmapGetPixel(bitmap, 18, 50, &color); + expect(Ok, stat); + todo_wine expect(0xff4700b8, color); + + /* Verify preset color gradient fill. */ + stat = GdipBitmapGetPixel(bitmap, 50, 50, &color); + expect(Ok, stat); + todo_wine expect(0xffff0000, color); + + stat = GdipBitmapGetPixel(bitmap, 50, 60, &color); + expect(Ok, stat); + todo_wine expect(0xff00ff00, color); + + GdipDeleteBrush(vertbrush); + GdipDeleteBrush(horizbrush); + GdipDeleteBrush(blendbrush); + GdipDeleteBrush(presetbrush); + GdipDeleteGraphics(graphics); + GdipDisposeImage((GpImage*)bitmap); + GdipDisposeImage((GpImage*)metafile); +} + START_TEST(metafile) { struct GdiplusStartupInput gdiplusStartupInput; @@ -3322,6 +3467,7 @@ START_TEST(metafile) test_drawdriverstring(); test_unknownfontdecode(); test_fillregion(); + test_lineargradient(); GdiplusShutdown(gdiplusToken); }
1
0
0
0
Zhiyi Zhang : winex11.drv: Remove the old virtual desktop display settings handler.
by Alexandre Julliard
23 Jul '20
23 Jul '20
Module: wine Branch: master Commit: 2a6de8d7f7d6f5ac018d8e330cfa580fc0c3b9e5 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=2a6de8d7f7d6f5ac018d8e33…
Author: Zhiyi Zhang <zzhang(a)codeweavers.com> Date: Wed Jul 22 15:25:21 2020 +0800 winex11.drv: Remove the old virtual desktop display settings handler. Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/winex11.drv/desktop.c | 81 +--------------------------------------------- 1 file changed, 1 insertion(+), 80 deletions(-) diff --git a/dlls/winex11.drv/desktop.c b/dlls/winex11.drv/desktop.c index ea269d8f2c..64f61d21e4 100644 --- a/dlls/winex11.drv/desktop.c +++ b/dlls/winex11.drv/desktop.c @@ -35,10 +35,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(x11drv); -/* data for resolution changing */ -static struct x11drv_mode_info *dd_modes; -static unsigned int dd_mode_count; - static unsigned int max_width; static unsigned int max_height; static unsigned int desktop_width; @@ -90,72 +86,6 @@ BOOL is_virtual_desktop(void) return root_window != DefaultRootWindow( gdi_display ); } -/* create the mode structures */ -static void make_modes(void) -{ - RECT primary_rect = get_primary_monitor_rect(); - unsigned int i; - unsigned int screen_width = primary_rect.right - primary_rect.left; - unsigned int screen_height = primary_rect.bottom - primary_rect.top; - - /* original specified desktop size */ - X11DRV_Settings_AddOneMode(screen_width, screen_height, 0, 60); - for (i=0; i<ARRAY_SIZE(screen_sizes); i++) - { - if ( (screen_sizes[i].width <= max_width) && (screen_sizes[i].height <= max_height) ) - { - if ( ( (screen_sizes[i].width != max_width) || (screen_sizes[i].height != max_height) ) && - ( (screen_sizes[i].width != screen_width) || (screen_sizes[i].height != screen_height) ) ) - { - /* only add them if they are smaller than the root window and unique */ - X11DRV_Settings_AddOneMode(screen_sizes[i].width, screen_sizes[i].height, 0, 60); - } - } - } - if ((max_width != screen_width) || (max_height != screen_height)) - { - /* root window size (if different from desktop window) */ - X11DRV_Settings_AddOneMode(max_width, max_height, 0, 60); - } -} - -static int X11DRV_desktop_GetCurrentMode(void) -{ - unsigned int i; - DWORD dwBpp = screen_bpp; - RECT primary_rect = get_primary_monitor_rect(); - - for (i=0; i<dd_mode_count; i++) - { - if ( (primary_rect.right - primary_rect.left == dd_modes[i].width) && - (primary_rect.bottom - primary_rect.top == dd_modes[i].height) && - (dwBpp == dd_modes[i].bpp)) - return i; - } - ERR("In unknown mode, returning default\n"); - return 0; -} - -static LONG X11DRV_desktop_SetCurrentMode(int mode) -{ - DWORD dwBpp = screen_bpp; - if (dwBpp != dd_modes[mode].bpp) - { - FIXME("Cannot change screen BPP from %d to %d\n", dwBpp, dd_modes[mode].bpp); - /* Ignore the depth mismatch - * - * Some (older) applications require a specific bit depth, this will allow them - * to run. X11drv performs a color depth conversion if needed. - */ - } - TRACE("Resizing Wine desktop window to %dx%d\n", dd_modes[mode].width, dd_modes[mode].height); - - desktop_width = dd_modes[mode].width; - desktop_height = dd_modes[mode].height; - X11DRV_DisplayDevices_Update( TRUE ); - return DISP_CHANGE_SUCCESSFUL; -} - /* Virtual desktop display settings handler */ static BOOL X11DRV_desktop_get_id( const WCHAR *device_name, ULONG_PTR *id ) { @@ -372,16 +302,7 @@ void X11DRV_init_desktop( Window win, unsigned int width, unsigned int height ) TRACE("Display device functions are now handled by: Virtual Desktop\n"); X11DRV_DisplayDevices_Init( TRUE ); - /* initialize the available resolutions */ - dd_modes = X11DRV_Settings_SetHandlers("desktop", - X11DRV_desktop_GetCurrentMode, - X11DRV_desktop_SetCurrentMode, - ARRAY_SIZE(screen_sizes)+2, 1); - make_modes(); - X11DRV_Settings_AddDepthModes(); - dd_mode_count = X11DRV_Settings_GetModeCount(); - - /* TODO: Remove the old display settings handler once the migration to the new interface is done */ + /* Initialize virtual desktop display settings handler */ settings_handler.name = "Virtual Desktop"; settings_handler.priority = 1000; settings_handler.get_id = X11DRV_desktop_get_id;
1
0
0
0
Zhiyi Zhang : winex11.drv: Support setting virtual desktop display mode using the new display settings handler interface.
by Alexandre Julliard
23 Jul '20
23 Jul '20
Module: wine Branch: master Commit: 6f305dd881e16f77f9eb183684d04b0b8746b769 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=6f305dd881e16f77f9eb1836…
Author: Zhiyi Zhang <zzhang(a)codeweavers.com> Date: Wed Jul 22 15:25:08 2020 +0800 winex11.drv: Support setting virtual desktop display mode using the new display settings handler interface. Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/winex11.drv/desktop.c | 11 ++++ dlls/winex11.drv/settings.c | 123 +++++++++++++++++++++++++++++++++++++++++++- dlls/winex11.drv/x11drv.h | 6 +++ 3 files changed, 139 insertions(+), 1 deletion(-) diff --git a/dlls/winex11.drv/desktop.c b/dlls/winex11.drv/desktop.c index 72a315e35b..ea269d8f2c 100644 --- a/dlls/winex11.drv/desktop.c +++ b/dlls/winex11.drv/desktop.c @@ -251,6 +251,16 @@ static BOOL X11DRV_desktop_get_current_mode( ULONG_PTR id, DEVMODEW *mode ) return TRUE; } +static LONG X11DRV_desktop_set_current_mode( ULONG_PTR id, DEVMODEW *mode ) +{ + if (mode->dmFields & DM_BITSPERPEL && mode->dmBitsPerPel != screen_bpp) + WARN("Cannot change screen color depth from %dbits to %dbits!\n", screen_bpp, mode->dmBitsPerPel); + + desktop_width = mode->dmPelsWidth; + desktop_height = mode->dmPelsHeight; + return DISP_CHANGE_SUCCESSFUL; +} + static void query_desktop_work_area( RECT *rc_work ) { static const WCHAR trayW[] = {'S','h','e','l','l','_','T','r','a','y','W','n','d',0}; @@ -378,6 +388,7 @@ void X11DRV_init_desktop( Window win, unsigned int width, unsigned int height ) settings_handler.get_modes = X11DRV_desktop_get_modes; settings_handler.free_modes = X11DRV_desktop_free_modes; settings_handler.get_current_mode = X11DRV_desktop_get_current_mode; + settings_handler.set_current_mode = X11DRV_desktop_set_current_mode; X11DRV_Settings_SetHandler( &settings_handler ); } diff --git a/dlls/winex11.drv/settings.c b/dlls/winex11.drv/settings.c index 8fc8cbd44d..28c405ae0e 100644 --- a/dlls/winex11.drv/settings.c +++ b/dlls/winex11.drv/settings.c @@ -30,6 +30,7 @@ #include "winreg.h" #include "wingdi.h" #include "wine/debug.h" +#include "wine/heap.h" #include "wine/unicode.h" WINE_DEFAULT_DEBUG_CHANNEL(x11settings); @@ -466,6 +467,53 @@ BOOL is_detached_mode(const DEVMODEW *mode) mode->dmPelsHeight == 0; } +/* Get the full display mode with all the necessary fields set. + * Return NULL on failure. Caller should free the returned mode. */ +static DEVMODEW *get_full_mode(ULONG_PTR id, const DEVMODEW *dev_mode) +{ + DEVMODEW *modes, *full_mode, *found_mode = NULL; + UINT mode_count, mode_idx; + + if (!handler.get_modes(id, 0, &modes, &mode_count)) + return NULL; + + for (mode_idx = 0; mode_idx < mode_count; ++mode_idx) + { + found_mode = (DEVMODEW *)((BYTE *)modes + (sizeof(*modes) + modes[0].dmDriverExtra) * mode_idx); + + if (dev_mode->dmFields & DM_BITSPERPEL && found_mode->dmBitsPerPel != dev_mode->dmBitsPerPel) + continue; + if (dev_mode->dmFields & DM_PELSWIDTH && found_mode->dmPelsWidth != dev_mode->dmPelsWidth) + continue; + if (dev_mode->dmFields & DM_PELSHEIGHT && found_mode->dmPelsHeight != dev_mode->dmPelsHeight) + continue; + if (dev_mode->dmFields & DM_DISPLAYFREQUENCY && + dev_mode->dmDisplayFrequency && + found_mode->dmDisplayFrequency && + dev_mode->dmDisplayFrequency != 1 && + dev_mode->dmDisplayFrequency != found_mode->dmDisplayFrequency) + continue; + + break; + } + + if (!found_mode || mode_idx == mode_count) + { + handler.free_modes(modes); + return NULL; + } + + if (!(full_mode = heap_alloc(sizeof(*found_mode) + found_mode->dmDriverExtra))) + { + handler.free_modes(modes); + return NULL; + } + + memcpy(full_mode, found_mode, sizeof(*found_mode) + found_mode->dmDriverExtra); + handler.free_modes(modes); + return full_mode; +} + /*********************************************************************** * ChangeDisplaySettingsEx (X11DRV.@) * @@ -475,9 +523,82 @@ LONG CDECL X11DRV_ChangeDisplaySettingsEx( LPCWSTR devname, LPDEVMODEW devmode, { WCHAR primary_adapter[CCHDEVICENAME]; char bpp_buffer[16], freq_buffer[18]; - DEVMODEW default_mode; + DEVMODEW default_mode, *full_mode; + ULONG_PTR id; + LONG ret; DWORD i; + /* Use the new interface if it is available */ + if (!handler.name) + goto old_interface; + + if (!get_primary_adapter(primary_adapter)) + return DISP_CHANGE_FAILED; + + if (!devname && !devmode) + { + default_mode.dmSize = sizeof(default_mode); + if (!EnumDisplaySettingsExW(primary_adapter, ENUM_REGISTRY_SETTINGS, &default_mode, 0)) + { + ERR("Default mode not found for %s!\n", wine_dbgstr_w(primary_adapter)); + return DISP_CHANGE_BADMODE; + } + + devname = primary_adapter; + devmode = &default_mode; + } + + if (!handler.get_id(devname, &id)) + { + ERR("Failed to get %s device id.\n", wine_dbgstr_w(devname)); + return DISP_CHANGE_BADPARAM; + } + + if (is_detached_mode(devmode)) + { + FIXME("Detaching adapters is currently unsupported.\n"); + return DISP_CHANGE_SUCCESSFUL; + } + + if (!(full_mode = get_full_mode(id, devmode))) + { + ERR("Failed to find a valid mode.\n"); + return DISP_CHANGE_BADMODE; + } + + if (flags & CDS_UPDATEREGISTRY && !write_registry_settings(devname, full_mode)) + { + ERR("Failed to write %s display settings to registry.\n", wine_dbgstr_w(devname)); + heap_free(full_mode); + return DISP_CHANGE_NOTUPDATED; + } + + if (lstrcmpiW(primary_adapter, devname)) + { + FIXME("Changing non-primary adapter %s settings is currently unsupported.\n", + wine_dbgstr_w(devname)); + heap_free(full_mode); + return DISP_CHANGE_SUCCESSFUL; + } + + if (flags & (CDS_TEST | CDS_NORESET)) + { + heap_free(full_mode); + return DISP_CHANGE_SUCCESSFUL; + } + + TRACE("handler:%s device:%s position:(%d,%d) resolution:%ux%u frequency:%uHz depth:%ubits " + "orientation:%#x.\n", handler.name, wine_dbgstr_w(devname), full_mode->u1.s2.dmPosition.x, + full_mode->u1.s2.dmPosition.y, full_mode->dmPelsWidth, full_mode->dmPelsHeight, + full_mode->dmDisplayFrequency, full_mode->dmBitsPerPel, full_mode->u1.s2.dmDisplayOrientation); + + ret = handler.set_current_mode(id, full_mode); + if (ret == DISP_CHANGE_SUCCESSFUL) + X11DRV_DisplayDevices_Update(TRUE); + heap_free(full_mode); + return ret; + +old_interface: if (!get_primary_adapter(primary_adapter)) return DISP_CHANGE_FAILED; diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index b19e0e3e80..1c6b666227 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -697,6 +697,12 @@ struct x11drv_settings_handler * * Return FALSE on failure with parameters unchanged and error code set. Return TRUE on success */ BOOL (*get_current_mode)(ULONG_PTR id, DEVMODEW *mode); + + /* set_current_mode() will be called to change the display mode of the display device of id. + * mode must be a valid mode from get_modes() with optional fields, such as dmPosition set. + * + * Return DISP_CHANGE_*, same as ChangeDisplaySettingsExW() return values */ + LONG (*set_current_mode)(ULONG_PTR id, DEVMODEW *mode); }; extern void X11DRV_Settings_SetHandler(const struct x11drv_settings_handler *handler) DECLSPEC_HIDDEN;
1
0
0
0
Zhiyi Zhang : winex11.drv: Cache display modes for X11DRV_EnumDisplaySettingsEx().
by Alexandre Julliard
23 Jul '20
23 Jul '20
Module: wine Branch: master Commit: 679ff720902b8e5d5d750b980084bdcdc9a051ed URL:
https://source.winehq.org/git/wine.git/?a=commit;h=679ff720902b8e5d5d750b98…
Author: Zhiyi Zhang <zzhang(a)codeweavers.com> Date: Wed Jul 22 15:24:56 2020 +0800 winex11.drv: Cache display modes for X11DRV_EnumDisplaySettingsEx(). Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/winex11.drv/settings.c | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/dlls/winex11.drv/settings.c b/dlls/winex11.drv/settings.c index 097710fc1c..8fc8cbd44d 100644 --- a/dlls/winex11.drv/settings.c +++ b/dlls/winex11.drv/settings.c @@ -130,6 +130,21 @@ unsigned int X11DRV_Settings_GetModeCount(void) /* TODO: Remove the old display settings handler interface once all backends are migrated to the new interface */ static struct x11drv_settings_handler handler; +/* Cached display modes for a device, protected by modes_section */ +static WCHAR cached_device_name[CCHDEVICENAME]; +static DWORD cached_flags; +static DEVMODEW *cached_modes; +static UINT cached_mode_count; + +static CRITICAL_SECTION modes_section; +static CRITICAL_SECTION_DEBUG modes_critsect_debug = +{ + 0, 0, &modes_section, + {&modes_critsect_debug.ProcessLocksList, &modes_critsect_debug.ProcessLocksList}, + 0, 0, {(DWORD_PTR)(__FILE__ ": modes_section")} +}; +static CRITICAL_SECTION modes_section = {&modes_critsect_debug, -1, 0, 0, 0, 0}; + void X11DRV_Settings_SetHandler(const struct x11drv_settings_handler *new_handler) { if (new_handler->priority > handler.priority) @@ -353,22 +368,34 @@ BOOL CDECL X11DRV_EnumDisplaySettingsEx( LPCWSTR name, DWORD n, LPDEVMODEW devmo goto done; } - if (!handler.get_id(name, &id) || !handler.get_modes(id, flags, &modes, &mode_count)) + EnterCriticalSection(&modes_section); + if (n == 0 || lstrcmpiW(cached_device_name, name) || cached_flags != flags) { - ERR("Failed to get %s supported display modes.\n", wine_dbgstr_w(name)); - return FALSE; + if (!handler.get_id(name, &id) || !handler.get_modes(id, flags, &modes, &mode_count)) + { + ERR("Failed to get %s supported display modes.\n", wine_dbgstr_w(name)); + LeaveCriticalSection(&modes_section); + return FALSE; + } + + if (cached_modes) + handler.free_modes(cached_modes); + lstrcpyW(cached_device_name, name); + cached_flags = flags; + cached_modes = modes; + cached_mode_count = mode_count; } - if (n >= mode_count) + if (n >= cached_mode_count) { + LeaveCriticalSection(&modes_section); WARN("handler:%s device:%s mode index:%#x not found.\n", handler.name, wine_dbgstr_w(name), n); - handler.free_modes(modes); SetLastError(ERROR_NO_MORE_FILES); return FALSE; } - memcpy(devmode, (BYTE *)modes + (sizeof(*modes) + modes[0].dmDriverExtra) * n, sizeof(*devmode)); - handler.free_modes(modes); + memcpy(devmode, (BYTE *)cached_modes + (sizeof(*cached_modes) + cached_modes[0].dmDriverExtra) * n, sizeof(*devmode)); + LeaveCriticalSection(&modes_section); done: /* Set generic fields */
1
0
0
0
Zhiyi Zhang : winex11.drv: Support virtual desktop display mode enumeration using the new display settings handler interface.
by Alexandre Julliard
23 Jul '20
23 Jul '20
Module: wine Branch: master Commit: 0b0ac41981006514616abdd4c4b6922cf66be7b6 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=0b0ac41981006514616abdd4…
Author: Zhiyi Zhang <zzhang(a)codeweavers.com> Date: Wed Jul 22 15:24:41 2020 +0800 winex11.drv: Support virtual desktop display mode enumeration using the new display settings handler interface. Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/winex11.drv/desktop.c | 68 +++++++++++++++++++++++++++++++++++++++++++++ dlls/winex11.drv/settings.c | 25 ++++++++++++++++- dlls/winex11.drv/x11drv.h | 17 ++++++++++++ 3 files changed, 109 insertions(+), 1 deletion(-) diff --git a/dlls/winex11.drv/desktop.c b/dlls/winex11.drv/desktop.c index d3dcf90fb9..72a315e35b 100644 --- a/dlls/winex11.drv/desktop.c +++ b/dlls/winex11.drv/desktop.c @@ -168,6 +168,72 @@ static BOOL X11DRV_desktop_get_id( const WCHAR *device_name, ULONG_PTR *id ) return TRUE; } +static void add_desktop_mode( DEVMODEW *mode, DWORD depth, DWORD width, DWORD height ) +{ + mode->dmSize = sizeof(*mode); + mode->dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | + DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY; + mode->u1.s2.dmDisplayOrientation = DMDO_DEFAULT; + mode->dmBitsPerPel = depth; + mode->dmPelsWidth = width; + mode->dmPelsHeight = height; + mode->u2.dmDisplayFlags = 0; + mode->dmDisplayFrequency = 60; +} + +static BOOL X11DRV_desktop_get_modes( ULONG_PTR id, DWORD flags, DEVMODEW **new_modes, UINT *mode_count ) +{ + UINT depth_idx, size_idx, mode_idx = 0; + UINT screen_width, screen_height; + RECT primary_rect; + DEVMODEW *modes; + + primary_rect = get_primary_monitor_rect(); + screen_width = primary_rect.right - primary_rect.left; + screen_height = primary_rect.bottom - primary_rect.top; + + /* Allocate memory for modes in different color depths */ + if (!(modes = heap_calloc( (ARRAY_SIZE(screen_sizes) + 2) * DEPTH_COUNT, sizeof(*modes))) ) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return FALSE; + } + + for (depth_idx = 0; depth_idx < DEPTH_COUNT; ++depth_idx) + { + for (size_idx = 0; size_idx < ARRAY_SIZE(screen_sizes); ++size_idx) + { + if (screen_sizes[size_idx].width > max_width || + screen_sizes[size_idx].height > max_height) + continue; + + if (screen_sizes[size_idx].width == max_width && + screen_sizes[size_idx].height == max_height) + continue; + + if (screen_sizes[size_idx].width == screen_width && + screen_sizes[size_idx].height == screen_height) + continue; + + add_desktop_mode( &modes[mode_idx++], depths[depth_idx], screen_sizes[size_idx].width, + screen_sizes[size_idx].height ); + } + + add_desktop_mode( &modes[mode_idx++], depths[depth_idx], screen_width, screen_height ); + if (max_width != screen_width || max_height != screen_height) + add_desktop_mode( &modes[mode_idx++], depths[depth_idx], max_width, max_height ); + } + + *new_modes = modes; + *mode_count = mode_idx; + return TRUE; +} + +static void X11DRV_desktop_free_modes( DEVMODEW *modes ) +{ + heap_free( modes ); +} + static BOOL X11DRV_desktop_get_current_mode( ULONG_PTR id, DEVMODEW *mode ) { RECT primary_rect = get_primary_monitor_rect(); @@ -309,6 +375,8 @@ void X11DRV_init_desktop( Window win, unsigned int width, unsigned int height ) settings_handler.name = "Virtual Desktop"; settings_handler.priority = 1000; settings_handler.get_id = X11DRV_desktop_get_id; + settings_handler.get_modes = X11DRV_desktop_get_modes; + settings_handler.free_modes = X11DRV_desktop_free_modes; settings_handler.get_current_mode = X11DRV_desktop_get_current_mode; X11DRV_Settings_SetHandler( &settings_handler ); } diff --git a/dlls/winex11.drv/settings.c b/dlls/winex11.drv/settings.c index e0dee95154..097710fc1c 100644 --- a/dlls/winex11.drv/settings.c +++ b/dlls/winex11.drv/settings.c @@ -42,6 +42,7 @@ static unsigned int dd_max_modes = 0; */ static const unsigned int depths_24[] = {8, 16, 24}; static const unsigned int depths_32[] = {8, 16, 32}; +const unsigned int *depths; /* pointers to functions that actually do the hard stuff */ static int (*pGetCurrentMode)(void); @@ -158,6 +159,9 @@ static LONG X11DRV_nores_SetCurrentMode(int mode) void X11DRV_Settings_Init(void) { RECT primary = get_host_primary_monitor_rect(); + + depths = screen_bpp == 32 ? depths_32 : depths_24; + X11DRV_Settings_SetHandlers("NoRes", X11DRV_nores_GetCurrentMode, X11DRV_nores_SetCurrentMode, @@ -321,10 +325,12 @@ BOOL CDECL X11DRV_EnumDisplaySettingsEx( LPCWSTR name, DWORD n, LPDEVMODEW devmo { static const WCHAR dev_name[CCHDEVICENAME] = { 'W','i','n','e',' ','X','1','1',' ','d','r','i','v','e','r',0 }; + DEVMODEW *modes; + UINT mode_count; ULONG_PTR id; /* Use the new interface if it is available */ - if (!handler.name || (n != ENUM_REGISTRY_SETTINGS && n != ENUM_CURRENT_SETTINGS)) + if (!handler.name) goto old_interface; if (n == ENUM_REGISTRY_SETTINGS) @@ -347,6 +353,23 @@ BOOL CDECL X11DRV_EnumDisplaySettingsEx( LPCWSTR name, DWORD n, LPDEVMODEW devmo goto done; } + if (!handler.get_id(name, &id) || !handler.get_modes(id, flags, &modes, &mode_count)) + { + ERR("Failed to get %s supported display modes.\n", wine_dbgstr_w(name)); + return FALSE; + } + + if (n >= mode_count) + { + WARN("handler:%s device:%s mode index:%#x not found.\n", handler.name, wine_dbgstr_w(name), n); + handler.free_modes(modes); + SetLastError(ERROR_NO_MORE_FILES); + return FALSE; + } + + memcpy(devmode, (BYTE *)modes + (sizeof(*modes) + modes[0].dmDriverExtra) * n, sizeof(*devmode)); + handler.free_modes(modes); + done: /* Set generic fields */ devmode->dmSize = FIELD_OFFSET(DEVMODEW, dmICMMethod); diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 49059e09b7..b19e0e3e80 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -657,6 +657,9 @@ struct x11drv_mode_info unsigned int refresh_rate; }; +#define DEPTH_COUNT 3 +extern const unsigned int *depths DECLSPEC_HIDDEN; + /* Required functions for changing and enumerating display settings */ struct x11drv_settings_handler { @@ -672,6 +675,20 @@ struct x11drv_settings_handler * Return FALSE if the device can not be found and TRUE on success */ BOOL (*get_id)(const WCHAR *device_name, ULONG_PTR *id); + /* get_modes() will be called to get a list of supported modes of the device of id in modes + * with respect to flags, which could be 0, EDS_RAWMODE or EDS_ROTATEDMODE. If the implementation + * uses dmDriverExtra then every DEVMODEW in the list must have the same dmDriverExtra value + * + * Following fields in DEVMODE must be valid: + * dmSize, dmDriverExtra, dmFields, dmDisplayOrientation, dmBitsPerPel, dmPelsWidth, dmPelsHeight, + * dmDisplayFlags and dmDisplayFrequency + * + * Return FALSE on failure with parameters unchanged and error code set. Return TRUE on success */ + BOOL (*get_modes)(ULONG_PTR id, DWORD flags, DEVMODEW **modes, UINT *mode_count); + + /* free_modes() will be called to free the mode list returned from get_modes() */ + void (*free_modes)(DEVMODEW *modes); + /* get_current_mode() will be called to get the current display mode of the device of id * * Following fields in DEVMODE must be valid:
1
0
0
0
Zhiyi Zhang : winex11.drv: Migrate the virtual desktop display settings handler to a new interface.
by Alexandre Julliard
23 Jul '20
23 Jul '20
Module: wine Branch: master Commit: dd13b274104b561f05873e8acdc4bfd34bbe796e URL:
https://source.winehq.org/git/wine.git/?a=commit;h=dd13b274104b561f05873e8a…
Author: Zhiyi Zhang <zzhang(a)codeweavers.com> Date: Wed Jul 22 15:24:30 2020 +0800 winex11.drv: Migrate the virtual desktop display settings handler to a new interface. The old display settings handler interface can only support one adapter. Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/winex11.drv/desktop.c | 41 ++++++++++++++++++++++++++++++++++++++ dlls/winex11.drv/settings.c | 48 +++++++++++++++++++++++++++++++++++++++++++++ dlls/winex11.drv/x11drv.h | 27 +++++++++++++++++++++++++ 3 files changed, 116 insertions(+) diff --git a/dlls/winex11.drv/desktop.c b/dlls/winex11.drv/desktop.c index b5894d5e02..d3dcf90fb9 100644 --- a/dlls/winex11.drv/desktop.c +++ b/dlls/winex11.drv/desktop.c @@ -2,6 +2,7 @@ * X11DRV desktop window handling * * Copyright 2001 Alexandre Julliard + * Copyright 2020 Zhiyi Zhang for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,6 +23,9 @@ #include <X11/cursorfont.h> #include <X11/Xlib.h> +#define NONAMELESSSTRUCT +#define NONAMELESSUNION + #include "x11drv.h" /* avoid conflict with field names in included win32 headers */ @@ -152,6 +156,35 @@ static LONG X11DRV_desktop_SetCurrentMode(int mode) return DISP_CHANGE_SUCCESSFUL; } +/* Virtual desktop display settings handler */ +static BOOL X11DRV_desktop_get_id( const WCHAR *device_name, ULONG_PTR *id ) +{ + WCHAR primary_adapter[CCHDEVICENAME]; + + if (!get_primary_adapter( primary_adapter ) || lstrcmpiW( primary_adapter, device_name )) + return FALSE; + + *id = 0; + return TRUE; +} + +static BOOL X11DRV_desktop_get_current_mode( ULONG_PTR id, DEVMODEW *mode ) +{ + RECT primary_rect = get_primary_monitor_rect(); + + mode->dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | + DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY | DM_POSITION; + mode->u1.s2.dmDisplayOrientation = DMDO_DEFAULT; + mode->dmBitsPerPel = screen_bpp; + mode->dmPelsWidth = primary_rect.right - primary_rect.left; + mode->dmPelsHeight = primary_rect.bottom - primary_rect.top; + mode->u2.dmDisplayFlags = 0; + mode->dmDisplayFrequency = 60; + mode->u1.s2.dmPosition.x = 0; + mode->u1.s2.dmPosition.y = 0; + return TRUE; +} + static void query_desktop_work_area( RECT *rc_work ) { static const WCHAR trayW[] = {'S','h','e','l','l','_','T','r','a','y','W','n','d',0}; @@ -242,6 +275,7 @@ static void X11DRV_desktop_free_monitors( struct x11drv_monitor *monitors ) void X11DRV_init_desktop( Window win, unsigned int width, unsigned int height ) { RECT primary_rect = get_host_primary_monitor_rect(); + struct x11drv_settings_handler settings_handler; root_window = win; managed_mode = FALSE; /* no managed windows in desktop mode */ @@ -270,6 +304,13 @@ void X11DRV_init_desktop( Window win, unsigned int width, unsigned int height ) make_modes(); X11DRV_Settings_AddDepthModes(); dd_mode_count = X11DRV_Settings_GetModeCount(); + + /* TODO: Remove the old display settings handler once the migration to the new interface is done */ + settings_handler.name = "Virtual Desktop"; + settings_handler.priority = 1000; + settings_handler.get_id = X11DRV_desktop_get_id; + settings_handler.get_current_mode = X11DRV_desktop_get_current_mode; + X11DRV_Settings_SetHandler( &settings_handler ); } diff --git a/dlls/winex11.drv/settings.c b/dlls/winex11.drv/settings.c index bbbb6fdf0a..e0dee95154 100644 --- a/dlls/winex11.drv/settings.c +++ b/dlls/winex11.drv/settings.c @@ -2,6 +2,7 @@ * Wine X11drv display settings functions * * Copyright 2003 Alexander James Pasadyn + * Copyright 2020 Zhiyi Zhang for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -125,6 +126,18 @@ unsigned int X11DRV_Settings_GetModeCount(void) return dd_mode_count; } +/* TODO: Remove the old display settings handler interface once all backends are migrated to the new interface */ +static struct x11drv_settings_handler handler; + +void X11DRV_Settings_SetHandler(const struct x11drv_settings_handler *new_handler) +{ + if (new_handler->priority > handler.priority) + { + handler = *new_handler; + TRACE("Display settings are now handled by: %s.\n", handler.name); + } +} + /*********************************************************************** * Default handlers if resolution switching is not enabled * @@ -308,7 +321,42 @@ BOOL CDECL X11DRV_EnumDisplaySettingsEx( LPCWSTR name, DWORD n, LPDEVMODEW devmo { static const WCHAR dev_name[CCHDEVICENAME] = { 'W','i','n','e',' ','X','1','1',' ','d','r','i','v','e','r',0 }; + ULONG_PTR id; + + /* Use the new interface if it is available */ + if (!handler.name || (n != ENUM_REGISTRY_SETTINGS && n != ENUM_CURRENT_SETTINGS)) + goto old_interface; + + if (n == ENUM_REGISTRY_SETTINGS) + { + if (!read_registry_settings(name, devmode)) + { + ERR("Failed to get %s registry display settings.\n", wine_dbgstr_w(name)); + return FALSE; + } + goto done; + } + + if (n == ENUM_CURRENT_SETTINGS) + { + if (!handler.get_id(name, &id) || !handler.get_current_mode(id, devmode)) + { + ERR("Failed to get %s current display settings.\n", wine_dbgstr_w(name)); + return FALSE; + } + goto done; + } + +done: + /* Set generic fields */ + devmode->dmSize = FIELD_OFFSET(DEVMODEW, dmICMMethod); + devmode->dmDriverExtra = 0; + devmode->dmSpecVersion = DM_SPECVERSION; + devmode->dmDriverVersion = DM_SPECVERSION; + lstrcpyW(devmode->dmDeviceName, dev_name); + return TRUE; +old_interface: devmode->dmSize = FIELD_OFFSET(DEVMODEW, dmICMMethod); devmode->dmSpecVersion = DM_SPECVERSION; devmode->dmDriverVersion = DM_SPECVERSION; diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 9bbb48f1ee..49059e09b7 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -657,6 +657,33 @@ struct x11drv_mode_info unsigned int refresh_rate; }; +/* Required functions for changing and enumerating display settings */ +struct x11drv_settings_handler +{ + /* A name to tell what host driver is used */ + const char *name; + + /* Higher priority can override handlers with a lower priority */ + UINT priority; + + /* get_id() will be called to map a device name, e.g., \\.\DISPLAY1 to a driver specific id. + * Following functions use this id to identify the device. + * + * Return FALSE if the device can not be found and TRUE on success */ + BOOL (*get_id)(const WCHAR *device_name, ULONG_PTR *id); + + /* get_current_mode() will be called to get the current display mode of the device of id + * + * Following fields in DEVMODE must be valid: + * dmFields, dmDisplayOrientation, dmBitsPerPel, dmPelsWidth, dmPelsHeight, dmDisplayFlags, + * dmDisplayFrequency and dmPosition + * + * Return FALSE on failure with parameters unchanged and error code set. Return TRUE on success */ + BOOL (*get_current_mode)(ULONG_PTR id, DEVMODEW *mode); +}; + +extern void X11DRV_Settings_SetHandler(const struct x11drv_settings_handler *handler) DECLSPEC_HIDDEN; + extern void X11DRV_init_desktop( Window win, unsigned int width, unsigned int height ) DECLSPEC_HIDDEN; extern void X11DRV_resize_desktop(BOOL) DECLSPEC_HIDDEN; extern BOOL is_virtual_desktop(void) DECLSPEC_HIDDEN;
1
0
0
0
Zhiyi Zhang : winex11.drv: Allow reporting a virtual desktop mode with the same width or height as the current mode.
by Alexandre Julliard
23 Jul '20
23 Jul '20
Module: wine Branch: master Commit: 6436600db5a680d016bc428326d0f67417315ad7 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=6436600db5a680d016bc4283…
Author: Zhiyi Zhang <zzhang(a)codeweavers.com> Date: Wed Jul 22 15:24:14 2020 +0800 winex11.drv: Allow reporting a virtual desktop mode with the same width or height as the current mode. Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/winex11.drv/desktop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlls/winex11.drv/desktop.c b/dlls/winex11.drv/desktop.c index 5a9e0f59ae..b5894d5e02 100644 --- a/dlls/winex11.drv/desktop.c +++ b/dlls/winex11.drv/desktop.c @@ -108,7 +108,7 @@ static void make_modes(void) } } } - if ((max_width != screen_width) && (max_height != screen_height)) + if ((max_width != screen_width) || (max_height != screen_height)) { /* root window size (if different from desktop window) */ X11DRV_Settings_AddOneMode(max_width, max_height, 0, 60);
1
0
0
0
← Newer
1
...
12
13
14
15
16
17
18
...
83
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
Results per page:
10
25
50
100
200