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
February 2021
----- 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
2 participants
915 discussions
Start a n
N
ew thread
Jacek Caban : ntdll: Use xsavec in x86_64 syscall dispatcher.
by Alexandre Julliard
22 Feb '21
22 Feb '21
Module: wine Branch: master Commit: a8856381ed9a7187a6564960893617f31ec3e8ff URL:
https://source.winehq.org/git/wine.git/?a=commit;h=a8856381ed9a7187a6564960…
Author: Jacek Caban <jacek(a)codeweavers.com> Date: Mon Feb 22 18:04:31 2021 +0100 ntdll: Use xsavec in x86_64 syscall dispatcher. Signed-off-by: Jacek Caban <jacek(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/ntdll/unix/signal_x86_64.c | 5 ++++- dlls/ntdll/unix/system.c | 6 ++++++ include/winternl.h | 1 + tools/winebuild/import.c | 13 ++++++++++++- 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index 88e5eace003..df83094750e 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -2814,9 +2814,12 @@ void *signal_init_syscalls(void) void *ptr, *syscall_dispatcher; extern void __wine_syscall_dispatcher_xsave(void) DECLSPEC_HIDDEN; + extern void __wine_syscall_dispatcher_xsavec(void) DECLSPEC_HIDDEN; NtQuerySystemInformation( SystemCpuInformation, &cpu_info, sizeof(cpu_info), NULL ); - if (cpu_info.FeatureSet & CPU_FEATURE_XSAVE) + if (cpu_info.FeatureSet & CPU_FEATURE_XSAVEC) + syscall_dispatcher = __wine_syscall_dispatcher_xsavec; + else if (cpu_info.FeatureSet & CPU_FEATURE_XSAVE) syscall_dispatcher = __wine_syscall_dispatcher_xsave; else syscall_dispatcher = __wine_syscall_dispatcher; diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c index 6cf044d496f..27ecfae365f 100644 --- a/dlls/ntdll/unix/system.c +++ b/dlls/ntdll/unix/system.c @@ -305,6 +305,12 @@ static void get_cpuinfo( SYSTEM_CPU_INFORMATION *info ) if (regs3[1] & (1 << 5)) info->FeatureSet |= CPU_FEATURE_AVX2; } + if (info->FeatureSet & CPU_FEATURE_XSAVE) + { + do_cpuid( 0x0000000d, regs3 ); /* get XSAVE details */ + if (regs3[0] & 2) info->FeatureSet |= CPU_FEATURE_XSAVEC; + } + if (regs[1] == AUTH && regs[3] == ENTI && regs[2] == CAMD) { info->Level = (regs2[0] >> 8) & 0xf; /* family */ diff --git a/include/winternl.h b/include/winternl.h index 76feca83596..3beecf10ff6 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -1754,6 +1754,7 @@ typedef struct _SYSTEM_CPU_INFORMATION { /* FIXME: following values are made up, actual flags are unknown */ #define CPU_FEATURE_SSSE3 0x00008000 /* SSSE3 instructions */ +#define CPU_FEATURE_XSAVEC 0x00400000 /* XSAVEC instructions */ #define CPU_FEATURE_SSE41 0x01000000 /* SSE41 instructions */ #define CPU_FEATURE_SSE42 0x02000000 /* SSE42 instructions */ #define CPU_FEATURE_AVX 0x40000000 /* AVX instructions */ diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index a01694ffb9c..2fa9d3d430b 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -1534,7 +1534,17 @@ static void output_syscall_dispatcher( int count, const char *variant ) output( "\tmovq %%rdx,0x200(%%r12)\n" ); output( "\tmovq %%rdx,0x208(%%r12)\n" ); output( "\tmovq %%rdx,0x210(%%r12)\n" ); - output( "\txsave64 (%%r12)\n" ); + if (!strcmp( variant, "_xsavec" )) + { + output( "\tmovq %%rdx,0x218(%%r12)\n" ); + output( "\tmovq %%rdx,0x220(%%r12)\n" ); + output( "\tmovq %%rdx,0x228(%%r12)\n" ); + output( "\tmovq %%rdx,0x230(%%r12)\n" ); + output( "\tmovq %%rdx,0x238(%%r12)\n" ); + output( "\txsavec64 (%%r12)\n" ); + } + else + output( "\txsave64 (%%r12)\n" ); output( "\tmovq %%rsi,%%rdx\n" ); } output( "\tmovq %%gs:0x30,%%rcx\n" ); @@ -1740,6 +1750,7 @@ void output_syscalls( DLLSPEC *spec ) { case CPU_x86_64: output_syscall_dispatcher( count, "_xsave" ); + output_syscall_dispatcher( count, "_xsavec" ); break; default: break;
1
0
0
0
Jacek Caban : ntdll: Use syscall dispatcher for restoring context in x86_64 NtSetContextThread implementation.
by Alexandre Julliard
22 Feb '21
22 Feb '21
Module: wine Branch: master Commit: 437bef6ac15dea892904769b46a4cafb80ed9eb4 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=437bef6ac15dea892904769b…
Author: Jacek Caban <jacek(a)codeweavers.com> Date: Mon Feb 22 18:04:16 2021 +0100 ntdll: Use syscall dispatcher for restoring context in x86_64 NtSetContextThread implementation. Signed-off-by: Jacek Caban <jacek(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/ntdll/unix/server.c | 5 ++++- dlls/ntdll/unix/signal_arm.c | 10 ++++++++++ dlls/ntdll/unix/signal_arm64.c | 10 ++++++++++ dlls/ntdll/unix/signal_i386.c | 11 +++++++++++ dlls/ntdll/unix/signal_x86_64.c | 29 ++++++++++++++++++++++------- dlls/ntdll/unix/unix_private.h | 1 + tools/winebuild/import.c | 13 ++++++++++++- 7 files changed, 70 insertions(+), 9 deletions(-) diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c index 6af8effe9e1..4f149c0f644 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -726,7 +726,10 @@ NTSTATUS WINAPI NtContinue( CONTEXT *context, BOOLEAN alertable ) status = server_select( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, 0, NULL, NULL, &apc ); if (status == STATUS_USER_APC) invoke_apc( context, &apc ); } - return NtSetContextThread( GetCurrentThread(), context ); + status = NtSetContextThread( GetCurrentThread(), context ); + if (!status && (context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) + signal_restore_full_cpu_context(); + return status; } diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c index 2de58925c84..cb4695939f5 100644 --- a/dlls/ntdll/unix/signal_arm.c +++ b/dlls/ntdll/unix/signal_arm.c @@ -332,6 +332,16 @@ __ASM_GLOBAL_FUNC( set_cpu_context, "pop {pc}" ) +/*********************************************************************** + * signal_restore_full_cpu_context + * + * Restore full context from syscall frame + */ +void signal_restore_full_cpu_context(void) +{ +} + + /*********************************************************************** * get_server_context_flags * diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c index 9a36746f5bc..80cc59d0743 100644 --- a/dlls/ntdll/unix/signal_arm64.c +++ b/dlls/ntdll/unix/signal_arm64.c @@ -406,6 +406,16 @@ static void restore_fpu( CONTEXT *context, ucontext_t *sigcontext ) } +/*********************************************************************** + * signal_restore_full_cpu_context + * + * Restore full context from syscall frame + */ +void signal_restore_full_cpu_context(void) +{ +} + + /*********************************************************************** * get_server_context_flags * diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index 09529a1ea96..4d03153bd1f 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -807,6 +807,17 @@ static inline void restore_xstate( const CONTEXT *context ) __asm__ volatile( "xrstor %0" : : "m"(*xrstor_base), "a" (4), "d" (0) ); } + +/*********************************************************************** + * signal_restore_full_cpu_context + * + * Restore full context from syscall frame + */ +void signal_restore_full_cpu_context(void) +{ +} + + /*********************************************************************** * fpux_to_fpu * diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index b5040852cbe..88e5eace003 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -1591,7 +1591,12 @@ __ASM_GLOBAL_FUNC( set_full_cpu_context, "leaq 0x70(%rsp),%rsp\n\t" "iretq" ) -static void signal_restore_full_cpu_context(void) +/*********************************************************************** + * signal_restore_full_cpu_context + * + * Restore full context from syscall frame + */ +void signal_restore_full_cpu_context(void) { struct syscall_xsave *xsave = get_syscall_xsave( get_syscall_frame() ); SYSTEM_CPU_INFORMATION cpu_info; @@ -1863,9 +1868,6 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context ) else if (xs->CompactionMask & XSTATE_MASK_GSSE) xsave->xstate.Mask &= ~XSTATE_MASK_GSSE; } - - if (!(flags & CONTEXT_INTEGER)) frame->rax = STATUS_SUCCESS; - signal_restore_full_cpu_context(); return STATUS_SUCCESS; } @@ -2614,11 +2616,24 @@ static void quit_handler( int signal, siginfo_t *siginfo, void *ucontext ) */ static void usr1_handler( int signal, siginfo_t *siginfo, void *ucontext ) { + struct syscall_frame *frame = amd64_thread_data()->syscall_frame; struct xcontext context; + if (frame) + { + DECLSPEC_ALIGN(64) XSTATE xs; + context.c.ContextFlags = CONTEXT_FULL; + context_init_xstate( &context.c, &xs ); - save_context( &context, ucontext ); - wait_suspend( &context.c ); - restore_context( &context, ucontext ); + NtGetContextThread( GetCurrentThread(), &context.c ); + wait_suspend( &context.c ); + NtSetContextThread( GetCurrentThread(), &context.c ); + } + else + { + save_context( &context, ucontext ); + wait_suspend( &context.c ); + restore_context( &context, ucontext ); + } } diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 65f526d0f7d..c98b11701e4 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -214,6 +214,7 @@ extern void DECLSPEC_NORETURN signal_start_thread( PRTL_THREAD_START_ROUTINE ent extern void DECLSPEC_NORETURN signal_exit_thread( int status, void (*func)(int) ) DECLSPEC_HIDDEN; extern void DECLSPEC_NORETURN exec_process( NTSTATUS status ) DECLSPEC_HIDDEN; extern void __wine_syscall_dispatcher(void) DECLSPEC_HIDDEN; +extern void signal_restore_full_cpu_context(void) DECLSPEC_HIDDEN; extern void fill_vm_counters( VM_COUNTERS_EX *pvmi, int unix_pid ) DECLSPEC_HIDDEN; extern NTSTATUS cdrom_DeviceIoControl( HANDLE device, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user, diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index 0fddbaf6134..a01694ffb9c 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -1559,7 +1559,18 @@ static void output_syscall_dispatcher( int count, const char *variant ) output( "\tcallq *(%%r10,%%r11,8)\n" ); output( "2:\tmovq %%gs:0x30,%%rcx\n" ); output( "\tmovq $0,0x328(%%rcx)\n" ); - output( "\tfxrstor64 (%%r12)\n" ); + if (!*variant) + { + output( "\tfxrstor64 (%%r12)\n" ); + } + else + { + output( "\tmovq %%rax,%%r11\n" ); + output( "\tmovl $7,%%eax\n" ); + output( "\txorq %%rdx,%%rdx\n" ); + output( "\txrstor64 (%%r12)\n" ); + output( "\tmovq %%r11,%%rax\n" ); + } output( "\tmovq -0x30(%%rbp),%%r15\n" ); output( "\tmovq -0x38(%%rbp),%%r14\n" ); output( "\tmovq -0x40(%%rbp),%%r13\n" );
1
0
0
0
Jacek Caban : ntdll: Use NtContinue in RtlRestoreContext.
by Alexandre Julliard
22 Feb '21
22 Feb '21
Module: wine Branch: master Commit: bdf4b3b400465e736b809a355b69f9a3edf108ef URL:
https://source.winehq.org/git/wine.git/?a=commit;h=bdf4b3b400465e736b809a35…
Author: Jacek Caban <jacek(a)codeweavers.com> Date: Mon Feb 22 18:02:05 2021 +0100 ntdll: Use NtContinue in RtlRestoreContext. Signed-off-by: Jacek Caban <jacek(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/ntdll/signal_arm64.c | 2 +- dlls/ntdll/signal_x86_64.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c index e198f4e607e..25bb407658f 100644 --- a/dlls/ntdll/signal_arm64.c +++ b/dlls/ntdll/signal_arm64.c @@ -1134,7 +1134,7 @@ void CDECL RtlRestoreContext( CONTEXT *context, EXCEPTION_RECORD *rec ) } TRACE( "returning to %lx stack %lx\n", context->Pc, context->Sp ); - NtSetContextThread( GetCurrentThread(), context ); + NtContinue( context, FALSE ); } /******************************************************************* diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index 7e90b109ad0..7e3387ba09e 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -1210,7 +1210,7 @@ void CDECL RtlRestoreContext( CONTEXT *context, EXCEPTION_RECORD *rec ) } TRACE( "returning to %p stack %p\n", (void *)context->Rip, (void *)context->Rsp ); - NtSetContextThread( GetCurrentThread(), context ); + NtContinue( context, FALSE ); }
1
0
0
0
Jacek Caban : ntdll: Use NtContinue in NtRaiseException.
by Alexandre Julliard
22 Feb '21
22 Feb '21
Module: wine Branch: master Commit: b3dfc903ef3b7a10860f24da7d18df7275ac349f URL:
https://source.winehq.org/git/wine.git/?a=commit;h=b3dfc903ef3b7a10860f24da…
Author: Jacek Caban <jacek(a)codeweavers.com> Date: Mon Feb 22 18:01:52 2021 +0100 ntdll: Use NtContinue in NtRaiseException. Signed-off-by: Jacek Caban <jacek(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/ntdll/unix/thread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index 9808fc610e3..00d29ae706b 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -428,7 +428,7 @@ NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL NTSTATUS status = send_debug_event( rec, context, first_chance ); if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED) - NtSetContextThread( GetCurrentThread(), context ); + return NtContinue( context, FALSE ); if (first_chance) call_user_exception_dispatcher( rec, context, pKiUserExceptionDispatcher );
1
0
0
0
Jacek Caban : ntdll: Use syscall frames in x86_64 NtSetContextThread implementation.
by Alexandre Julliard
22 Feb '21
22 Feb '21
Module: wine Branch: master Commit: 3ecd43dc6fabe072857139d513ae8e3a44861662 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=3ecd43dc6fabe072857139d5…
Author: Jacek Caban <jacek(a)codeweavers.com> Date: Mon Feb 22 18:01:47 2021 +0100 ntdll: Use syscall frames in x86_64 NtSetContextThread implementation. Signed-off-by: Jacek Caban <jacek(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/ntdll/unix/signal_x86_64.c | 163 ++++++++++++++++++++++++---------------- 1 file changed, 97 insertions(+), 66 deletions(-) diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index 8d3353e959d..b5040852cbe 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -1568,71 +1568,47 @@ static void restore_context( const struct xcontext *xcontext, ucontext_t *sigcon * * Set the new CPU context. */ -extern void set_full_cpu_context( const CONTEXT *context ); +extern void set_full_cpu_context(void); __ASM_GLOBAL_FUNC( set_full_cpu_context, - "subq $40,%rsp\n\t" - __ASM_SEH(".seh_stackalloc 0x40\n\t") - __ASM_SEH(".seh_endprologue\n\t") - __ASM_CFI(".cfi_adjust_cfa_offset 40\n\t") "movq %gs:0x30,%rdx\n\t" - "movw 0x38(%rdi),%ax\n\t" /* context->SegCs */ - "movq %rax,8(%rsp)\n\t" - "movw 0x42(%rdi),%ax\n\t" /* context->SegSs */ - "movq %rax,32(%rsp)\n\t" - "movq 0x44(%rdi),%rax\n\t" /* context->Eflags */ - "movq %rax,16(%rsp)\n\t" - "movq $0,0x328(%rdx)\n\t" /* amd64_thread_data()->syscall_frame */ - "movq 0x80(%rdi),%rcx\n\t" /* context->Rcx */ - "movq 0x88(%rdi),%rdx\n\t" /* context->Rdx */ - "movq 0x90(%rdi),%rbx\n\t" /* context->Rbx */ - "movq 0x98(%rdi),%rax\n\t" /* context->Rsp */ - "movq %rax,24(%rsp)\n\t" - "movq 0xa0(%rdi),%rbp\n\t" /* context->Rbp */ - "movq 0xa8(%rdi),%rsi\n\t" /* context->Rsi */ - "movq 0xb8(%rdi),%r8\n\t" /* context->R8 */ - "movq 0xc0(%rdi),%r9\n\t" /* context->R9 */ - "movq 0xc8(%rdi),%r10\n\t" /* context->R10 */ - "movq 0xd0(%rdi),%r11\n\t" /* context->R11 */ - "movq 0xd8(%rdi),%r12\n\t" /* context->R12 */ - "movq 0xe0(%rdi),%r13\n\t" /* context->R13 */ - "movq 0xe8(%rdi),%r14\n\t" /* context->R14 */ - "movq 0xf0(%rdi),%r15\n\t" /* context->R15 */ - "movq 0xf8(%rdi),%rax\n\t" /* context->Rip */ - "movq %rax,(%rsp)\n\t" - "fxrstor 0x100(%rdi)\n\t" /* context->FltSave */ - "movq 0x78(%rdi),%rax\n\t" /* context->Rax */ - "movq 0xb0(%rdi),%rdi\n\t" /* context->Rdi */ - "iretq" ); - - -/*********************************************************************** - * restore_xstate - * - * Restore the XState context. - */ -static void restore_xstate( const CONTEXT *context ) -{ - XSAVE_FORMAT *xrstor_base; - XSTATE *xs; - - if (!(user_shared_data->XState.EnabledFeatures && (xs = xstate_from_context( context )))) - return; - - xrstor_base = (XSAVE_FORMAT *)xs - 1; + "movq 0x328(%rdx),%rsp\n\t" /* amd64_thread_data()->syscall_frame */ + "movq $0,0x328(%rdx)\n\t" + "movq 0x00(%rsp),%rax\n\t" + "movq 0x08(%rsp),%rbx\n\t" + "movq 0x10(%rsp),%rcx\n\t" + "movq 0x18(%rsp),%rdx\n\t" + "movq 0x20(%rsp),%rsi\n\t" + "movq 0x28(%rsp),%rdi\n\t" + "movq 0x30(%rsp),%r8\n\t" + "movq 0x38(%rsp),%r9\n\t" + "movq 0x40(%rsp),%r10\n\t" + "movq 0x48(%rsp),%r11\n\t" + "movq 0x50(%rsp),%r12\n\t" + "movq 0x58(%rsp),%r13\n\t" + "movq 0x60(%rsp),%r14\n\t" + "movq 0x68(%rsp),%r15\n\t" + "movq 0x98(%rsp),%rbp\n\t" + "leaq 0x70(%rsp),%rsp\n\t" + "iretq" ) + +static void signal_restore_full_cpu_context(void) +{ + struct syscall_xsave *xsave = get_syscall_xsave( get_syscall_frame() ); + SYSTEM_CPU_INFORMATION cpu_info; - if (!(xs->CompactionMask & ((ULONG64)1 << 63))) + NtQuerySystemInformation( SystemCpuInformation, &cpu_info, sizeof(cpu_info), NULL ); + if (cpu_info.FeatureSet & CPU_FEATURE_XSAVE) { - /* Non-compacted xrstor will load Mxcsr regardless of the specified mask. Loading garbage there - * may lead to fault. We have only padding, no more used EXCEPTION_RECORD or unused context fields - * at the MxCsr restore location, so just put it there. */ - assert( (void *)&xrstor_base->MxCsr > (void *)context->VectorRegister ); - xrstor_base->MxCsr = context->u.FltSave.MxCsr; - xrstor_base->MxCsr_Mask = context->u.FltSave.MxCsr_Mask; + __asm__ volatile( "xrstor64 %0" : : "m"(xsave->xsave), "a" (7), "d" (0) ); } - - __asm__ volatile( "xrstor64 %0" : : "m"(*xrstor_base), "a" (4), "d" (0) ); + else + { + __asm__ volatile( "fxrstor64 %0" : : "m"(xsave->xsave) ); + } + set_full_cpu_context(); } + /*********************************************************************** * get_server_context_flags * @@ -1798,6 +1774,9 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context ) NTSTATUS ret = STATUS_SUCCESS; DWORD flags = context->ContextFlags & ~CONTEXT_AMD64; BOOL self = (handle == GetCurrentThread()); + struct syscall_frame *frame; + struct syscall_xsave *xsave; + XSTATE *xs; /* debug registers require a server call */ if (self && (flags & CONTEXT_DEBUG_REGISTERS)) @@ -1826,16 +1805,68 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context ) } } - restore_xstate( context ); - - if (flags & CONTEXT_FULL) + frame = amd64_thread_data()->syscall_frame; + xsave = get_syscall_xsave( frame ); + if (flags & CONTEXT_INTEGER) { - if (!(flags & CONTEXT_CONTROL)) - FIXME( "setting partial context (%x) not supported\n", flags ); - else - set_full_cpu_context( context ); + frame->rax = context->Rax; + frame->rbx = context->Rbx; + frame->rcx = context->Rcx; + frame->rdx = context->Rdx; + frame->rsi = context->Rsi; + frame->rdi = context->Rdi; + frame->r8 = context->R8; + frame->r9 = context->R9; + frame->r10 = context->R10; + frame->r11 = context->R11; + frame->r12 = context->R12; + frame->r13 = context->R13; + frame->r14 = context->R14; + frame->r15 = context->R15; } - return ret; + if (flags & CONTEXT_CONTROL) + { + frame->rsp = context->Rsp; + frame->rbp = context->Rbp; + frame->rip = context->Rip; + frame->eflags = context->EFlags; + frame->cs = context->SegCs; + frame->ss = context->SegSs; + } + if (flags & CONTEXT_SEGMENTS) + { + frame->ds = context->SegDs; + frame->es = context->SegEs; + frame->fs = context->SegFs; + frame->gs = context->SegGs; + } + if (flags & CONTEXT_FLOATING_POINT) + { + xsave->xsave = context->u.FltSave; + } + if (user_shared_data->XState.EnabledFeatures && (xs = xstate_from_context( context ))) + { + CONTEXT_EX *context_ex = (CONTEXT_EX *)(context + 1); + + if (context_ex->XState.Length < offsetof(XSTATE, YmmContext) + || context_ex->XState.Length > sizeof(XSTATE)) + return STATUS_INVALID_PARAMETER; + + if (xs->Mask & XSTATE_MASK_GSSE) + { + if (context_ex->XState.Length < sizeof(XSTATE)) + return STATUS_BUFFER_OVERFLOW; + + xsave->xstate.Mask |= XSTATE_MASK_GSSE; + memcpy( &xsave->xstate.YmmContext, &xs->YmmContext, sizeof(xs->YmmContext) ); + } + else if (xs->CompactionMask & XSTATE_MASK_GSSE) + xsave->xstate.Mask &= ~XSTATE_MASK_GSSE; + } + + if (!(flags & CONTEXT_INTEGER)) frame->rax = STATUS_SUCCESS; + signal_restore_full_cpu_context(); + return STATUS_SUCCESS; }
1
0
0
0
Nikolay Sivov : winegstreamer: Fully initialize MF object creation context.
by Alexandre Julliard
22 Feb '21
22 Feb '21
Module: wine Branch: master Commit: e162e7ea7f90e4f2b87817683a5e5bdb528d66ca URL:
https://source.winehq.org/git/wine.git/?a=commit;h=e162e7ea7f90e4f2b8781768…
Author: Nikolay Sivov <nsivov(a)codeweavers.com> Date: Mon Feb 22 21:32:47 2021 +0300 winegstreamer: Fully initialize MF object creation context. Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/winegstreamer/media_source.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index e69370d2513..74af8e41f48 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -1379,7 +1379,7 @@ static HRESULT WINAPI winegstreamer_stream_handler_BeginCreateObject(IMFByteStre if (FAILED(hr = MFCreateAsyncResult(NULL, callback, state, &caller))) return hr; - context = heap_alloc(sizeof(*context)); + context = heap_alloc_zero(sizeof(*context)); if (!context) { IMFAsyncResult_Release(caller);
1
0
0
0
Nikolay Sivov : dwrite/layout: Add support for character spacing attributes.
by Alexandre Julliard
22 Feb '21
22 Feb '21
Module: wine Branch: master Commit: 8dac512e8cb678d88fd99968db803965250432ec URL:
https://source.winehq.org/git/wine.git/?a=commit;h=8dac512e8cb678d88fd99968…
Author: Nikolay Sivov <nsivov(a)codeweavers.com> Date: Mon Feb 22 21:29:38 2021 +0300 dwrite/layout: Add support for character spacing attributes. Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/dwrite/layout.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++ dlls/dwrite/tests/layout.c | 4 +-- 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c index 3e5c0379609..38be4eeb2da 100644 --- a/dlls/dwrite/layout.c +++ b/dlls/dwrite/layout.c @@ -1144,6 +1144,82 @@ static HRESULT layout_shape_get_glyphs(struct dwrite_textlayout *layout, struct return hr; } +static struct layout_range_spacing *layout_get_next_spacing_range(struct dwrite_textlayout *layout, + struct layout_range_spacing *cur) +{ + return (struct layout_range_spacing *)LIST_ENTRY(list_next(&layout->spacing, &cur->h.entry), + struct layout_range_header, entry); +} + +static HRESULT layout_shape_apply_character_spacing(struct dwrite_textlayout *layout, struct shaping_context *context) +{ + struct regular_layout_run *run = context->run; + struct layout_range_spacing *first = NULL, *last = NULL, *cur; + unsigned int i, length, pos, start, end, g0, glyph_count; + struct layout_range_header *h; + UINT16 *clustermap; + + LIST_FOR_EACH_ENTRY(h, &layout->spacing, struct layout_range_header, entry) + { + if ((h->range.startPosition >= run->descr.textPosition && + h->range.startPosition <= run->descr.textPosition + run->descr.stringLength) || + (run->descr.textPosition >= h->range.startPosition && + run->descr.textPosition <= h->range.startPosition + h->range.length)) + { + if (!first) first = last = (struct layout_range_spacing *)h; + } + else if (last) break; + } + if (!first) return S_OK; + + if (!(clustermap = heap_calloc(run->descr.stringLength, sizeof(*clustermap)))) return E_OUTOFMEMORY; + + pos = run->descr.textPosition; + + for (cur = first;; cur = layout_get_next_spacing_range(layout, cur)) + { + float leading, trailing; + + /* The range current spacing settings apply to. */ + start = max(pos, cur->h.range.startPosition); + pos = end = min(pos + run->descr.stringLength, cur->h.range.startPosition + cur->h.range.length); + + /* Back to run-relative index. */ + start -= run->descr.textPosition; + end -= run->descr.textPosition; + + length = end - start; + + g0 = run->descr.clusterMap[start]; + + for (i = 0; i < length; ++i) + clustermap[i] = run->descr.clusterMap[start + i] - run->descr.clusterMap[start]; + + glyph_count = (end < run->descr.stringLength ? run->descr.clusterMap[end] + 1 : run->glyphcount) - g0; + + /* There is no direction argument for spacing interface, we have to swap arguments here to get desired output. */ + if (run->run.bidiLevel & 1) + { + leading = cur->trailing; + trailing = cur->leading; + } + else + { + leading = cur->leading; + trailing = cur->trailing; + } + IDWriteTextAnalyzer2_ApplyCharacterSpacing(context->analyzer, leading, trailing, cur->min_advance, + length, glyph_count, clustermap, &run->advances[g0], &run->offsets[g0], &context->glyph_props[g0], + &run->advances[g0], &run->offsets[g0]); + + if (cur == last) break; + } + + heap_free(clustermap); + + return S_OK; +} + static HRESULT layout_shape_get_positions(struct dwrite_textlayout *layout, struct shaping_context *context) { struct regular_layout_run *run = context->run; @@ -1176,6 +1252,9 @@ static HRESULT layout_shape_get_positions(struct dwrite_textlayout *layout, stru WARN("%s: failed to get glyph placement info, hr %#x.\n", debugstr_rundescr(&run->descr), hr); } + if (SUCCEEDED(hr)) + hr = layout_shape_apply_character_spacing(layout, context); + run->run.glyphAdvances = run->advances; run->run.glyphOffsets = run->offsets; diff --git a/dlls/dwrite/tests/layout.c b/dlls/dwrite/tests/layout.c index adc9503ffd9..43e62a39956 100644 --- a/dlls/dwrite/tests/layout.c +++ b/dlls/dwrite/tests/layout.c @@ -2121,8 +2121,8 @@ static void test_GetClusterMetrics(void) hr = IDWriteTextLayout_GetClusterMetrics(layout, metrics2, ARRAY_SIZE(metrics2), &count); ok(hr == S_OK, "got 0x%08x\n", hr); ok(count == 4, "got %u\n", count); - for (i = 0; i < count; i++) { -todo_wine + for (i = 0; i < count; ++i) + { ok(metrics2[i].width > metrics[i].width, "%u: got width %.2f, was %.2f\n", i, metrics2[i].width, metrics[i].width); ok(metrics2[i].length == 1, "%u: got length %u\n", i, metrics2[i].length);
1
0
0
0
Nikolay Sivov : dwrite: Use newer analyzer interface internally.
by Alexandre Julliard
22 Feb '21
22 Feb '21
Module: wine Branch: master Commit: f18acbfef3850c6ec7f568b28aea5be92c78916e URL:
https://source.winehq.org/git/wine.git/?a=commit;h=f18acbfef3850c6ec7f568b2…
Author: Nikolay Sivov <nsivov(a)codeweavers.com> Date: Mon Feb 22 21:29:37 2021 +0300 dwrite: Use newer analyzer interface internally. Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/dwrite/analyzer.c | 4 ++-- dlls/dwrite/dwrite_private.h | 2 +- dlls/dwrite/layout.c | 21 +++++++++++---------- dlls/dwrite/main.c | 2 +- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/dlls/dwrite/analyzer.c b/dlls/dwrite/analyzer.c index d0d769cb346..6b74a23540a 100644 --- a/dlls/dwrite/analyzer.c +++ b/dlls/dwrite/analyzer.c @@ -1844,9 +1844,9 @@ static const IDWriteTextAnalyzer2Vtbl textanalyzervtbl = static IDWriteTextAnalyzer2 textanalyzer = { &textanalyzervtbl }; -IDWriteTextAnalyzer *get_text_analyzer(void) +IDWriteTextAnalyzer2 *get_text_analyzer(void) { - return (IDWriteTextAnalyzer *)&textanalyzer; + return &textanalyzer; } static HRESULT WINAPI dwritenumbersubstitution_QueryInterface(IDWriteNumberSubstitution *iface, REFIID riid, void **obj) diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 13bef3ad36b..6528970635b 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -304,7 +304,7 @@ extern void set_en_localizedstring(IDWriteLocalizedStrings*,const WCHAR*) DEC extern void sort_localizedstrings(IDWriteLocalizedStrings*) DECLSPEC_HIDDEN; extern HRESULT get_system_fontcollection(IDWriteFactory7 *factory, IDWriteFontCollection1 **collection) DECLSPEC_HIDDEN; extern HRESULT get_eudc_fontcollection(IDWriteFactory7 *factory, IDWriteFontCollection3 **collection) DECLSPEC_HIDDEN; -extern IDWriteTextAnalyzer *get_text_analyzer(void) DECLSPEC_HIDDEN; +extern IDWriteTextAnalyzer2 *get_text_analyzer(void) DECLSPEC_HIDDEN; extern HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *reference_key, UINT32 key_size, IDWriteFontFile **font_file) DECLSPEC_HIDDEN; extern void init_local_fontfile_loader(void) DECLSPEC_HIDDEN; extern IDWriteFontFileLoader *get_local_fontfile_loader(void) DECLSPEC_HIDDEN; diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c index fc874541d74..3e5c0379609 100644 --- a/dlls/dwrite/layout.c +++ b/dlls/dwrite/layout.c @@ -790,7 +790,7 @@ static void layout_get_font_height(FLOAT emsize, DWRITE_FONT_METRICS *fontmetric static HRESULT layout_itemize(struct dwrite_textlayout *layout) { - IDWriteTextAnalyzer *analyzer; + IDWriteTextAnalyzer2 *analyzer; struct layout_range *range; struct layout_run *r; HRESULT hr = S_OK; @@ -818,14 +818,14 @@ static HRESULT layout_itemize(struct dwrite_textlayout *layout) } /* Initial splitting by script. */ - hr = IDWriteTextAnalyzer_AnalyzeScript(analyzer, (IDWriteTextAnalysisSource *)&layout->IDWriteTextAnalysisSource1_iface, + hr = IDWriteTextAnalyzer2_AnalyzeScript(analyzer, (IDWriteTextAnalysisSource *)&layout->IDWriteTextAnalysisSource1_iface, range->h.range.startPosition, get_clipped_range_length(layout, range), (IDWriteTextAnalysisSink *)&layout->IDWriteTextAnalysisSink1_iface); if (FAILED(hr)) break; /* Splitting further by bidi levels. */ - hr = IDWriteTextAnalyzer_AnalyzeBidi(analyzer, (IDWriteTextAnalysisSource *)&layout->IDWriteTextAnalysisSource1_iface, + hr = IDWriteTextAnalyzer2_AnalyzeBidi(analyzer, (IDWriteTextAnalysisSource *)&layout->IDWriteTextAnalysisSource1_iface, range->h.range.startPosition, get_clipped_range_length(layout, range), (IDWriteTextAnalysisSink *)&layout->IDWriteTextAnalysisSink1_iface); if (FAILED(hr)) @@ -962,7 +962,7 @@ fatal: struct shaping_context { - IDWriteTextAnalyzer *analyzer; + IDWriteTextAnalyzer2 *analyzer; struct regular_layout_run *run; DWRITE_SHAPING_GLYPH_PROPERTIES *glyph_props; DWRITE_SHAPING_TEXT_PROPERTIES *text_props; @@ -1109,7 +1109,7 @@ static HRESULT layout_shape_get_glyphs(struct dwrite_textlayout *layout, struct for (;;) { - hr = IDWriteTextAnalyzer_GetGlyphs(context->analyzer, run->descr.string, run->descr.stringLength, run->run.fontFace, + hr = IDWriteTextAnalyzer2_GetGlyphs(context->analyzer, run->descr.string, run->descr.stringLength, run->run.fontFace, run->run.isSideways, run->run.bidiLevel & 1, &run->sa, run->descr.localeName, NULL /* FIXME */, (const DWRITE_TYPOGRAPHIC_FEATURES **)context->user_features.features, context->user_features.range_lengths, context->user_features.range_count, max_count, run->clustermap, context->text_props, run->glyphs, @@ -1156,14 +1156,14 @@ static HRESULT layout_shape_get_positions(struct dwrite_textlayout *layout, stru /* Get advances and offsets. */ if (is_layout_gdi_compatible(layout)) - hr = IDWriteTextAnalyzer_GetGdiCompatibleGlyphPlacements(context->analyzer, run->descr.string, run->descr.clusterMap, + hr = IDWriteTextAnalyzer2_GetGdiCompatibleGlyphPlacements(context->analyzer, run->descr.string, run->descr.clusterMap, context->text_props, run->descr.stringLength, run->run.glyphIndices, context->glyph_props, run->glyphcount, run->run.fontFace, run->run.fontEmSize, layout->ppdip, &layout->transform, layout->measuringmode == DWRITE_MEASURING_MODE_GDI_NATURAL, run->run.isSideways, run->run.bidiLevel & 1, &run->sa, run->descr.localeName, (const DWRITE_TYPOGRAPHIC_FEATURES **)context->user_features.features, context->user_features.range_lengths, context->user_features.range_count, run->advances, run->offsets); else - hr = IDWriteTextAnalyzer_GetGlyphPlacements(context->analyzer, run->descr.string, run->descr.clusterMap, + hr = IDWriteTextAnalyzer2_GetGlyphPlacements(context->analyzer, run->descr.string, run->descr.clusterMap, context->text_props, run->descr.stringLength, run->run.glyphIndices, context->glyph_props, run->glyphcount, run->run.fontFace, run->run.fontEmSize, run->run.isSideways, run->run.bidiLevel & 1, &run->sa, run->descr.localeName, (const DWRITE_TYPOGRAPHIC_FEATURES **)context->user_features.features, @@ -1302,8 +1302,9 @@ static HRESULT layout_compute(struct dwrite_textlayout *layout) return S_OK; /* nominal breakpoints are evaluated only once, because string never changes */ - if (!layout->nominal_breakpoints) { - IDWriteTextAnalyzer *analyzer; + if (!layout->nominal_breakpoints) + { + IDWriteTextAnalyzer2 *analyzer; layout->nominal_breakpoints = heap_calloc(layout->len, sizeof(*layout->nominal_breakpoints)); if (!layout->nominal_breakpoints) @@ -1311,7 +1312,7 @@ static HRESULT layout_compute(struct dwrite_textlayout *layout) analyzer = get_text_analyzer(); - if (FAILED(hr = IDWriteTextAnalyzer_AnalyzeLineBreakpoints(analyzer, + if (FAILED(hr = IDWriteTextAnalyzer2_AnalyzeLineBreakpoints(analyzer, (IDWriteTextAnalysisSource *)&layout->IDWriteTextAnalysisSource1_iface, 0, layout->len, (IDWriteTextAnalysisSink *)&layout->IDWriteTextAnalysisSink1_iface))) WARN("Line breakpoints analysis failed, hr %#x.\n", hr); diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c index 560661983d0..864a44936c1 100644 --- a/dlls/dwrite/main.c +++ b/dlls/dwrite/main.c @@ -1243,7 +1243,7 @@ static HRESULT WINAPI dwritefactory_CreateTextAnalyzer(IDWriteFactory7 *iface, I { TRACE("%p, %p.\n", iface, analyzer); - *analyzer = get_text_analyzer(); + *analyzer = (IDWriteTextAnalyzer *)get_text_analyzer(); return S_OK; }
1
0
0
0
Nikolay Sivov : dwrite: Use correct glyph origins during rendering.
by Alexandre Julliard
22 Feb '21
22 Feb '21
Module: wine Branch: master Commit: 76f421b090523bb313975f5d3d6f399186be5189 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=76f421b090523bb313975f5d…
Author: Nikolay Sivov <nsivov(a)codeweavers.com> Date: Mon Feb 22 21:29:36 2021 +0300 dwrite: Use correct glyph origins during rendering. Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/dwrite/dwrite_private.h | 2 ++ dlls/dwrite/font.c | 57 ++++---------------------------------------- dlls/dwrite/freetype.c | 36 ++++++++++++++++------------ dlls/dwrite/main.c | 2 +- 4 files changed, 29 insertions(+), 68 deletions(-) diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 830c71f0abf..13bef3ad36b 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -347,6 +347,8 @@ extern HRESULT create_inmemory_fileloader(IDWriteInMemoryFontFileLoader **loader extern HRESULT create_font_resource(IDWriteFactory7 *factory, IDWriteFontFile *file, UINT32 face_index, IDWriteFontResource **resource) DECLSPEC_HIDDEN; extern HRESULT create_fontset_builder(IDWriteFactory7 *factory, IDWriteFontSetBuilder2 **ret) DECLSPEC_HIDDEN; +extern HRESULT compute_glyph_origins(DWRITE_GLYPH_RUN const *run, DWRITE_MEASURING_MODE measuring_mode, + D2D1_POINT_2F baseline_origin, DWRITE_MATRIX const *transform, D2D1_POINT_2F *origins) DECLSPEC_HIDDEN; struct dwrite_fontface; diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index e22e4abf271..ac8f5c0a7bb 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -5918,10 +5918,7 @@ float fontface_get_scaled_design_advance(struct dwrite_fontface *fontface, DWRIT HRESULT create_glyphrunanalysis(const struct glyphrunanalysis_desc *desc, IDWriteGlyphRunAnalysis **ret) { struct dwrite_glyphrunanalysis *analysis; - struct dwrite_fontface *fontface; - D2D_POINT_2F origin; - FLOAT rtl_factor; - UINT32 i; + unsigned int i; *ret = NULL; @@ -5977,57 +5974,13 @@ HRESULT create_glyphrunanalysis(const struct glyphrunanalysis_desc *desc, IDWrit } analysis->run.glyphIndices = analysis->glyphs; - - rtl_factor = desc->run->bidiLevel & 1 ? -1.0f : 1.0f; - memcpy(analysis->glyphs, desc->run->glyphIndices, desc->run->glyphCount*sizeof(*desc->run->glyphIndices)); - fontface = unsafe_impl_from_IDWriteFontFace(desc->run->fontFace); - - origin.x = desc->origin.x; - origin.y = desc->origin.y; - for (i = 0; i < desc->run->glyphCount; ++i) + compute_glyph_origins(desc->run, desc->measuring_mode, desc->origin, desc->transform, analysis->origins); + if (analysis->flags & RUNANALYSIS_USE_TRANSFORM) { - float advance; - - /* Use nominal advances if not provided by caller. */ - if (desc->run->glyphAdvances) - advance = rtl_factor * desc->run->glyphAdvances[i]; - else - advance = rtl_factor * fontface_get_scaled_design_advance(fontface, desc->measuring_mode, - desc->run->fontEmSize, 1.0f, desc->transform, desc->run->glyphIndices[i], desc->run->isSideways); - - analysis->origins[i] = origin; - if (desc->run->bidiLevel & 1) - { - if (desc->run->isSideways) - analysis->origins[i].y += advance; - else - analysis->origins[i].x += advance; - } - - /* Offsets are optional, appled to pre-transformed origin. */ - if (desc->run->glyphOffsets) { - FLOAT advanceoffset = rtl_factor * desc->run->glyphOffsets[i].advanceOffset; - FLOAT ascenderoffset = -desc->run->glyphOffsets[i].ascenderOffset; - - if (desc->run->isSideways) { - analysis->origins[i].x += ascenderoffset; - analysis->origins[i].y += advanceoffset; - } - else { - analysis->origins[i].x += advanceoffset; - analysis->origins[i].y += ascenderoffset; - } - } - - if (analysis->flags & RUNANALYSIS_USE_TRANSFORM) - transform_point(analysis->origins + i, &analysis->m); - - if (desc->run->isSideways) - origin.y += advance; - else - origin.x += advance; + for (i = 0; i < desc->run->glyphCount; ++i) + transform_point(&analysis->origins[i], &analysis->m); } *ret = &analysis->IDWriteGlyphRunAnalysis_iface; diff --git a/dlls/dwrite/freetype.c b/dlls/dwrite/freetype.c index 91e44d82f2b..32fa4cc97c3 100644 --- a/dlls/dwrite/freetype.c +++ b/dlls/dwrite/freetype.c @@ -488,8 +488,8 @@ HRESULT freetype_get_glyphrun_outline(IDWriteFontFace5 *fontface, float emSize, scaler.y_res = 0; EnterCriticalSection(&freetype_cs); - if (pFTC_Manager_LookupSize(cache_manager, &scaler, &size) == 0) { - float rtl_factor = is_rtl ? -1.0f : 1.0f; + if (pFTC_Manager_LookupSize(cache_manager, &scaler, &size) == 0) + { D2D1_POINT_2F origin; unsigned int i; @@ -501,7 +501,6 @@ HRESULT freetype_get_glyphrun_outline(IDWriteFontFace5 *fontface, float emSize, FLOAT ft_advance = size->face->glyph->metrics.horiAdvance >> 6; FT_Outline *outline = &size->face->glyph->outline; D2D1_POINT_2F glyph_origin; - float advance; FT_Matrix m; if (simulations & DWRITE_FONT_SIMULATIONS_BOLD) @@ -514,25 +513,32 @@ HRESULT freetype_get_glyphrun_outline(IDWriteFontFace5 *fontface, float emSize, pFT_Outline_Transform(outline, &m); - if (advances) - advance = rtl_factor * advances[i]; - else - advance = rtl_factor * ft_advance; - glyph_origin = origin; + if (is_rtl) - glyph_origin.x += advance; + { + glyph_origin.x -= ft_advance; - /* glyph offsets act as current glyph adjustment */ - if (offsets) + if (offsets) + { + glyph_origin.x -= offsets[i].advanceOffset; + glyph_origin.y -= offsets[i].ascenderOffset; + } + + origin.x -= advances ? advances[i] : ft_advance; + } + else { - glyph_origin.x += rtl_factor * offsets[i].advanceOffset; - glyph_origin.y -= offsets[i].ascenderOffset; + if (offsets) + { + glyph_origin.x += offsets[i].advanceOffset; + glyph_origin.y -= offsets[i].ascenderOffset; + } + + origin.x += advances ? advances[i] : ft_advance; } decompose_outline(outline, glyph_origin, sink); - - origin.x += advance; } } } diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c index 3b0505231bf..560661983d0 100644 --- a/dlls/dwrite/main.c +++ b/dlls/dwrite/main.c @@ -1550,7 +1550,7 @@ static HRESULT WINAPI dwritefactory4_TranslateColorGlyphRun(IDWriteFactory7 *ifa return E_NOTIMPL; } -static HRESULT compute_glyph_origins(DWRITE_GLYPH_RUN const *run, DWRITE_MEASURING_MODE measuring_mode, +HRESULT compute_glyph_origins(DWRITE_GLYPH_RUN const *run, DWRITE_MEASURING_MODE measuring_mode, D2D1_POINT_2F baseline_origin, DWRITE_MATRIX const *transform, D2D1_POINT_2F *origins) { struct dwrite_fontface *font_obj;
1
0
0
0
Nikolay Sivov : dwrite: Correct return glyph origins for RTL runs.
by Alexandre Julliard
22 Feb '21
22 Feb '21
Module: wine Branch: master Commit: 87bc6aac205cf3091e0b6ea91aeb1a8b5f05e710 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=87bc6aac205cf3091e0b6ea9…
Author: Nikolay Sivov <nsivov(a)codeweavers.com> Date: Mon Feb 22 21:29:35 2021 +0300 dwrite: Correct return glyph origins for RTL runs. Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/dwrite/main.c | 84 ++++++++++++++++-------------------------------- dlls/dwrite/tests/font.c | 1 - 2 files changed, 28 insertions(+), 57 deletions(-) diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c index 40c82b6cd05..3b0505231bf 100644 --- a/dlls/dwrite/main.c +++ b/dlls/dwrite/main.c @@ -1551,76 +1551,48 @@ static HRESULT WINAPI dwritefactory4_TranslateColorGlyphRun(IDWriteFactory7 *ifa } static HRESULT compute_glyph_origins(DWRITE_GLYPH_RUN const *run, DWRITE_MEASURING_MODE measuring_mode, - D2D1_POINT_2F baseline_origin, DWRITE_MATRIX const *transform, D2D1_POINT_2F *origins) + D2D1_POINT_2F baseline_origin, DWRITE_MATRIX const *transform, D2D1_POINT_2F *origins) { - IDWriteFontFace1 *fontface1 = NULL; - DWRITE_FONT_METRICS metrics; - FLOAT rtl_factor; - HRESULT hr; - UINT32 i; + struct dwrite_fontface *font_obj; + unsigned int i; + float advance; - rtl_factor = run->bidiLevel & 1 ? -1.0f : 1.0f; + font_obj = unsafe_impl_from_IDWriteFontFace(run->fontFace); - if (run->fontFace) { - IDWriteFontFace_GetMetrics(run->fontFace, &metrics); - if (FAILED(hr = IDWriteFontFace_QueryInterface(run->fontFace, &IID_IDWriteFontFace1, (void **)&fontface1))) - WARN("Failed to get IDWriteFontFace1, %#x.\n", hr); - } + for (i = 0; i < run->glyphCount; ++i) + { + origins[i] = baseline_origin; - for (i = 0; i < run->glyphCount; i++) { - FLOAT advance; + if (run->bidiLevel & 1) + { + advance = fontface_get_scaled_design_advance(font_obj, measuring_mode, run->fontEmSize, + 1.0f, transform, run->glyphIndices[i], run->isSideways); - /* Use nominal advances if not provided by caller. */ - if (run->glyphAdvances) - advance = rtl_factor * run->glyphAdvances[i]; - else { - INT32 a; + origins[i].x -= advance; - advance = 0.0f; - switch (measuring_mode) + if (run->glyphOffsets) { - case DWRITE_MEASURING_MODE_NATURAL: - if (SUCCEEDED(IDWriteFontFace1_GetDesignGlyphAdvances(fontface1, 1, run->glyphIndices + i, &a, - run->isSideways))) - advance = rtl_factor * get_scaled_advance_width(a, run->fontEmSize, &metrics); - break; - case DWRITE_MEASURING_MODE_GDI_CLASSIC: - case DWRITE_MEASURING_MODE_GDI_NATURAL: - if (SUCCEEDED(IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1, run->fontEmSize, - 1.0f, transform, measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL, - run->isSideways, 1, run->glyphIndices + i, &a))) - advance = rtl_factor * floorf(a * run->fontEmSize / metrics.designUnitsPerEm + 0.5f); - break; - default: - ; + origins[i].x -= run->glyphOffsets[i].advanceOffset; + origins[i].y -= run->glyphOffsets[i].ascenderOffset; } - } - origins[i] = baseline_origin; + baseline_origin.x -= run->glyphAdvances ? run->glyphAdvances[i] : advance; + } + else + { + if (run->glyphOffsets) + { + origins[i].x += run->glyphOffsets[i].advanceOffset; + origins[i].y -= run->glyphOffsets[i].ascenderOffset; + } - /* Apply offsets. */ - if (run->glyphOffsets) { - FLOAT advanceoffset = rtl_factor * run->glyphOffsets[i].advanceOffset; - FLOAT ascenderoffset = -run->glyphOffsets[i].ascenderOffset; + baseline_origin.x += run->glyphAdvances ? run->glyphAdvances[i] : + fontface_get_scaled_design_advance(font_obj, measuring_mode, run->fontEmSize, 1.0f, transform, + run->glyphIndices[i], run->isSideways); - if (run->isSideways) { - origins[i].x += ascenderoffset; - origins[i].y += advanceoffset; - } - else { - origins[i].x += advanceoffset; - origins[i].y += ascenderoffset; - } } - - if (run->isSideways) - baseline_origin.y += advance; - else - baseline_origin.x += advance; } - if (fontface1) - IDWriteFontFace1_Release(fontface1); return S_OK; } diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c index 872405b1639..d7ced109a2f 100644 --- a/dlls/dwrite/tests/font.c +++ b/dlls/dwrite/tests/font.c @@ -8468,7 +8468,6 @@ static void test_ComputeGlyphOrigins(void) ok(hr == S_OK, "%u: failed to compute glyph origins, hr %#x.\n", i, hr); for (j = 0; j < run.glyphCount; ++j) { - todo_wine_if(run.bidiLevel & 1) ok(!memcmp(&origins[j], &expected_origins[j], sizeof(origins[j])), "%u: unexpected origin[%u] (%f, %f) - (%f, %f).\n", i, j, origins[j].x, origins[j].y, expected_origins[j].x, expected_origins[j].y);
1
0
0
0
← Newer
1
...
18
19
20
21
22
23
24
...
92
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
84
85
86
87
88
89
90
91
92
Results per page:
10
25
50
100
200