Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- 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
August 2021
- 78 participants
- 2529 messages
[PATCH 2/2] ws2_32: Add tests for exclusive flag for IOCTL_AFD_POLL.
by Guillaume Charifi
Signed-off-by: Guillaume Charifi <guillaume.charifi(a)sfr.fr>
---
dlls/ws2_32/tests/afd.c | 73 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 72 insertions(+), 1 deletion(-)
diff --git a/dlls/ws2_32/tests/afd.c b/dlls/ws2_32/tests/afd.c
index eb7c8ee50de..2568f251b6f 100644
--- a/dlls/ws2_32/tests/afd.c
+++ b/dlls/ws2_32/tests/afd.c
@@ -148,8 +148,10 @@ static void test_poll(void)
const struct sockaddr_in bind_addr = {.sin_family = AF_INET, .sin_addr.s_addr = htonl(INADDR_LOOPBACK)};
char in_buffer[offsetof(struct afd_poll_params, sockets[3])];
char out_buffer[offsetof(struct afd_poll_params, sockets[3])];
+ char out_buffer1[offsetof(struct afd_poll_params, sockets[3])];
struct afd_poll_params *in_params = (struct afd_poll_params *)in_buffer;
struct afd_poll_params *out_params = (struct afd_poll_params *)out_buffer;
+ struct afd_poll_params *out_params1 = (struct afd_poll_params *)out_buffer1;
int large_buffer_size = 1024 * 1024;
SOCKET client, server, listener;
struct sockaddr_in addr;
@@ -157,13 +159,14 @@ static void test_poll(void)
IO_STATUS_BLOCK io;
LARGE_INTEGER now;
ULONG params_size;
- HANDLE event;
+ HANDLE event, event1;
int ret, len;
large_buffer = malloc(large_buffer_size);
memset(in_buffer, 0, sizeof(in_buffer));
memset(out_buffer, 0, sizeof(out_buffer));
event = CreateEventW(NULL, TRUE, FALSE, NULL);
+ event1 = CreateEventW(NULL, TRUE, FALSE, NULL);
listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
ret = bind(listener, (const struct sockaddr *)&bind_addr, sizeof(bind_addr));
@@ -208,10 +211,77 @@ static void test_poll(void)
IOCTL_AFD_POLL, in_params, params_size, out_params, params_size);
ok(ret == STATUS_INVALID_PARAMETER, "got %#x\n", ret);
+ /* Test exclusive flag */
+
+ client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+ in_params->timeout = -1000 * 10000;
+ in_params->count = 1;
+ in_params->exclusive = FALSE;
+ in_params->sockets[0].socket = client;
+ in_params->sockets[0].flags = ~0;
+ in_params->sockets[0].status = 0;
+
+ out_params->sockets[0].socket = 0;
+ out_params->sockets[0].flags = 0;
+ out_params->sockets[0].status = 0xdeadbeef;
+
+ ret = NtDeviceIoControlFile((HANDLE)listener, event, NULL, NULL, &io,
+ IOCTL_AFD_POLL, in_params, params_size, out_params, params_size);
+ ok(ret == STATUS_PENDING, "got %#x\n", ret);
+
+ in_params->timeout = 0x7fffffffffffffff; /* TIMEOUT_INFINITE */
+ in_params->exclusive = TRUE;
+
+ ret = NtDeviceIoControlFile((HANDLE)listener, event1, NULL, NULL, &io,
+ IOCTL_AFD_POLL, in_params, params_size, out_params1, params_size);
+ ok(ret == STATUS_PENDING, "got %#x\n", ret);
+
+ ret = WaitForSingleObject(event, 100);
+ ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
+ ok(!out_params->sockets[0].socket, "got socket %#Ix\n", out_params->sockets[0].socket);
+ ok(!out_params->sockets[0].flags, "got flags %#x\n", out_params->sockets[0].flags);
+ ok(out_params->sockets[0].status == 0xdeadbeef, "got status %#x\n", out_params->sockets[0].status);
+
+ closesocket(client);
+
+ ret = WaitForSingleObject(event, 100);
+ ok(!ret, "got %#x\n", ret);
+
+ client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+ out_params->sockets[0].socket = 0;
+ out_params->sockets[0].flags = 0;
+ out_params->sockets[0].status = 0xdeadbeef;
+
+ ret = NtDeviceIoControlFile((HANDLE)listener, event, NULL, NULL, &io,
+ IOCTL_AFD_POLL, in_params, params_size, out_params, params_size);
+ ok(ret == STATUS_PENDING, "got %#x\n", ret);
+
+ ret = NtDeviceIoControlFile((HANDLE)listener, event1, NULL, NULL, &io,
+ IOCTL_AFD_POLL, in_params, params_size, out_params1, params_size);
+ ok(ret == STATUS_PENDING, "got %#x\n", ret);
+
+ ret = WaitForSingleObject(event, 100);
+ ok(!ret, "got %#x\n", ret);
+ ok(io.Status == STATUS_SUCCESS, "got %#x\n", io.Status);
+ ok(io.Information == offsetof(struct afd_poll_params, sockets[0]), "got %#Ix\n", io.Information);
+ ok(out_params->timeout == 0x7fffffffffffffff, "got timeout %#I64x\n", out_params->timeout);
+ ok(!out_params->count, "got count %u\n", out_params->count);
+ ok(!out_params->sockets[0].socket, "got socket %#Ix\n", out_params->sockets[0].socket);
+ ok(!out_params->sockets[0].flags, "got flags %#x\n", out_params->sockets[0].flags);
+ ok(out_params->sockets[0].status == 0xdeadbeef, "got status %#x\n", out_params->sockets[0].status);
+
+ closesocket(client);
+
+ ret = WaitForSingleObject(event1, 100);
+ ok(!ret, "got %#x\n", ret);
+
/* Basic semantics of the ioctl. */
in_params->timeout = 0;
in_params->count = 1;
+ in_params->exclusive = FALSE;
in_params->sockets[0].socket = listener;
in_params->sockets[0].flags = ~0;
in_params->sockets[0].status = 0xdeadbeef;
@@ -743,6 +813,7 @@ static void test_poll(void)
closesocket(server);
CloseHandle(event);
+ CloseHandle(event1);
free(large_buffer);
}
--
2.33.0
Aug. 31, 2021
[PATCH 1/2 v2] ntdll/socket: Implement exclusive flag for IOCTL_AFD_POLL.
by Guillaume Charifi
Signed-off-by: Guillaume Charifi <guillaume.charifi(a)sfr.fr>
---
dlls/ntdll/unix/socket.c | 6 ++---
include/wine/afd.h | 2 +-
include/wine/server_protocol.h | 5 ++--
server/protocol.def | 1 +
server/request.h | 1 +
server/sock.c | 46 +++++++++++++++++++++++++++++++---
server/trace.c | 3 ++-
7 files changed, 54 insertions(+), 10 deletions(-)
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c
index 8469def786a..b1b90b363ee 100644
--- a/dlls/ntdll/unix/socket.c
+++ b/dlls/ntdll/unix/socket.c
@@ -747,12 +747,11 @@ static NTSTATUS sock_poll( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, voi
|| in_size < offsetof( struct afd_poll_params, sockets[params->count] ))
return STATUS_INVALID_PARAMETER;
- TRACE( "timeout %s, count %u, unknown %#x, padding (%#x, %#x, %#x), sockets[0] {%04lx, %#x}\n",
- wine_dbgstr_longlong(params->timeout), params->count, params->unknown,
+ TRACE( "timeout %s, count %u, exclusive %u, padding (%#x, %#x, %#x), sockets[0] {%04lx, %#x}\n",
+ wine_dbgstr_longlong(params->timeout), params->count, params->exclusive,
params->padding[0], params->padding[1], params->padding[2],
params->sockets[0].socket, params->sockets[0].flags );
- if (params->unknown) FIXME( "unknown boolean is %#x\n", params->unknown );
if (params->padding[0]) FIXME( "padding[0] is %#x\n", params->padding[0] );
if (params->padding[1]) FIXME( "padding[1] is %#x\n", params->padding[1] );
if (params->padding[2]) FIXME( "padding[2] is %#x\n", params->padding[2] );
@@ -793,6 +792,7 @@ static NTSTATUS sock_poll( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, voi
SERVER_START_REQ( poll_socket )
{
req->async = server_async( handle, &async->io, event, apc, apc_user, iosb_client_ptr(io) );
+ req->exclusive = !!params->exclusive;
req->timeout = params->timeout;
wine_server_add_data( req, input, params->count * sizeof(*input) );
wine_server_set_reply( req, async->sockets, params->count * sizeof(async->sockets[0]) );
diff --git a/include/wine/afd.h b/include/wine/afd.h
index e67ecae25a9..f4682f464e8 100644
--- a/include/wine/afd.h
+++ b/include/wine/afd.h
@@ -104,7 +104,7 @@ struct afd_poll_params
{
LONGLONG timeout;
unsigned int count;
- BOOLEAN unknown;
+ BOOLEAN exclusive;
BOOLEAN padding[3];
struct
{
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index bb4862c9669..14518f0bf6f 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -1761,7 +1761,8 @@ struct poll_socket_output
struct poll_socket_request
{
struct request_header __header;
- char __pad_12[4];
+ char exclusive;
+ char __pad_13[3];
async_data_t async;
timeout_t timeout;
/* VARARG(sockets,poll_socket_input); */
@@ -6252,7 +6253,7 @@ union generic_reply
/* ### protocol_version begin ### */
-#define SERVER_PROTOCOL_VERSION 726
+#define SERVER_PROTOCOL_VERSION 727
/* ### protocol_version end ### */
diff --git a/server/protocol.def b/server/protocol.def
index 133d6ad0552..8eefdaae17f 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1450,6 +1450,7 @@ struct poll_socket_output
/* Perform an async poll on a socket */
@REQ(poll_socket)
+ char exclusive;
async_data_t async; /* async I/O parameters */
timeout_t timeout; /* timeout */
VARARG(sockets,poll_socket_input); /* list of sockets to poll */
diff --git a/server/request.h b/server/request.h
index 18a6a2df3c7..f1c8f1c5432 100644
--- a/server/request.h
+++ b/server/request.h
@@ -1045,6 +1045,7 @@ C_ASSERT( sizeof(struct recv_socket_request) == 64 );
C_ASSERT( FIELD_OFFSET(struct recv_socket_reply, wait) == 8 );
C_ASSERT( FIELD_OFFSET(struct recv_socket_reply, options) == 12 );
C_ASSERT( sizeof(struct recv_socket_reply) == 16 );
+C_ASSERT( FIELD_OFFSET(struct poll_socket_request, exclusive) == 12 );
C_ASSERT( FIELD_OFFSET(struct poll_socket_request, async) == 16 );
C_ASSERT( FIELD_OFFSET(struct poll_socket_request, timeout) == 56 );
C_ASSERT( sizeof(struct poll_socket_request) == 64 );
diff --git a/server/sock.c b/server/sock.c
index 50bfc08e145..cf4e1ac34b2 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -128,6 +128,7 @@ struct poll_req
struct async *async;
struct iosb *iosb;
struct timeout_user *timeout;
+ char exclusive;
unsigned int count;
struct poll_socket_output *output;
struct
@@ -2853,8 +2854,8 @@ static int poll_single_socket( struct sock *sock, int mask )
return get_poll_flags( sock, pollfd.revents ) & mask;
}
-static int poll_socket( struct sock *poll_sock, struct async *async, timeout_t timeout,
- unsigned int count, const struct poll_socket_input *input )
+static int poll_socket( struct sock *poll_sock, struct async *async, char exclusive,
+ timeout_t timeout, unsigned int count, const struct poll_socket_input *input )
{
struct poll_socket_output *output;
struct poll_req *req;
@@ -2893,11 +2894,50 @@ static int poll_socket( struct sock *poll_sock, struct async *async, timeout_t t
req->sockets[i].flags = input[i].flags;
}
+ req->exclusive = exclusive;
req->count = count;
req->async = (struct async *)grab_object( async );
req->iosb = async_get_iosb( async );
req->output = output;
+ if (exclusive)
+ {
+ int has_shared = FALSE;
+ struct poll_req *areq;
+
+ LIST_FOR_EACH_ENTRY( areq, &poll_list, struct poll_req, entry )
+ {
+ if (!areq->exclusive)
+ {
+ has_shared = TRUE;
+ break;
+ }
+ }
+
+ LIST_FOR_EACH_ENTRY( areq, &poll_list, struct poll_req, entry )
+ {
+ if (has_shared)
+ break;
+
+ for (i = 0; i < areq->count; ++i)
+ {
+ struct sock *asock = areq->sockets[i].sock;
+
+ for (j = 0; j < req->count; ++j)
+ {
+ if (asock == req->sockets[j].sock)
+ {
+ areq->iosb->status = STATUS_SUCCESS;
+ areq->iosb->out_data = areq->output;
+ areq->iosb->out_size = areq->count * sizeof(*areq->output);
+ async_terminate( areq->async, STATUS_ALERTED );
+ break;
+ }
+ }
+ }
+ }
+ }
+
list_add_tail( &poll_list, &req->entry );
async_set_completion_callback( async, free_poll_req, req );
queue_async( &poll_sock->poll_q, async );
@@ -3312,7 +3352,7 @@ DECL_HANDLER(poll_socket)
if ((async = create_request_async( sock->fd, get_fd_comp_flags( sock->fd ), &req->async )))
{
- reply->wait = async_handoff( async, poll_socket( sock, async, req->timeout, count, input ), NULL, 0 );
+ reply->wait = async_handoff( async, poll_socket( sock, async, req->exclusive, req->timeout, count, input ), NULL, 0 );
reply->options = get_fd_options( sock->fd );
release_object( async );
}
diff --git a/server/trace.c b/server/trace.c
index 4e91d933a5d..567c54c4df7 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -2122,7 +2122,8 @@ static void dump_recv_socket_reply( const struct recv_socket_reply *req )
static void dump_poll_socket_request( const struct poll_socket_request *req )
{
- dump_async_data( " async=", &req->async );
+ fprintf( stderr, " exclusive=%c", req->exclusive );
+ dump_async_data( ", async=", &req->async );
dump_timeout( ", timeout=", &req->timeout );
dump_varargs_poll_socket_input( ", sockets=", cur_size );
}
--
2.33.0
Aug. 31, 2021
Re: [PATCH vkd3d 3/5] vkd3d-shader/hlsl: Write SM4 negation instructions.
by Matteo Bruni
On Mon, Aug 30, 2021 at 7:21 PM Zebediah Figura <zfigura(a)codeweavers.com> wrote:
>
> Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
> ---
> Makefile.am | 5 +----
> libs/vkd3d-shader/hlsl_sm4.c | 32 ++++++++++++++++++++++++++++++++
> 2 files changed, 33 insertions(+), 4 deletions(-)
> diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c
> index ace2eb66..160da47f 100644
> --- a/libs/vkd3d-shader/hlsl_sm4.c
> +++ b/libs/vkd3d-shader/hlsl_sm4.c
> @@ -561,6 +561,7 @@ struct sm4_register
> unsigned int idx_count;
> enum vkd3d_sm4_dimension dim;
> uint32_t immconst_uint[4];
> + unsigned int mod;
> };
>
> struct sm4_instruction
> @@ -710,6 +711,8 @@ static uint32_t sm4_register_order(const struct sm4_register *reg)
> if (reg->type == VKD3D_SM4_RT_IMMCONST)
> order += reg->dim == VKD3D_SM4_DIMENSION_VEC4 ? 4 : 1;
> order += reg->idx_count;
> + if (reg->mod)
> + ++order;
> return order;
> }
Something that came to my mind at least twice while looking at that
function... Do you know e.g. by random looks to DXC's sources what the
size of a register in the bytecode is supposed to be called? "Order"
feels like a curious choice for a name.
No need to go investigate, just wondering if you happened to see anything.
Aug. 31, 2021
Re: [PATCH vkd3d 5/5] vkd3d-shader/hlsl: Use the modifiers location when validating modifiers on casts.
by Matteo Bruni
Signed-off-by: Matteo Bruni <mbruni(a)codeweavers.com>
Aug. 31, 2021
Re: [PATCH vkd3d 4/5] vkd3d-shader/hlsl: Merge the "type" and "base_type" rules.
by Matteo Bruni
Signed-off-by: Matteo Bruni <mbruni(a)codeweavers.com>
---
I guess the original choice was mostly a "defensive" one: it's
generally better to start with a restrictive grammar and then remove
constraints as necessary rather than the other way around.
Aug. 31, 2021
Re: [PATCH vkd3d 3/5] vkd3d-shader/hlsl: Write SM4 negation instructions.
by Matteo Bruni
Signed-off-by: Matteo Bruni <mbruni(a)codeweavers.com>
Aug. 31, 2021
Re: [PATCH vkd3d 2/5] vkd3d-shader/hlsl: Write SM4 division instructions.
by Matteo Bruni
Signed-off-by: Matteo Bruni <mbruni(a)codeweavers.com>
Aug. 31, 2021
Re: [PATCH vkd3d 1/5] vkd3d-shader/hlsl: Write SM4 multiplication instructions.
by Matteo Bruni
Signed-off-by: Matteo Bruni <mbruni(a)codeweavers.com>
Aug. 31, 2021
Re: [PATCH 0/5] winemac.drv: Layer-backed views
by Chip Davis
Ugh. Don't know how the patchset summary was lost. It's supposed to say something to the effect of:
This patchset enables layer-backed views for the macOS graphics driver,
and sets the drawn bits directly into the layer. We are able to do this now,
because the minimum version is now 10.8. It is my hope that this will ease the
implementation of full Retina support as well as drawing to other processes'
windows.
August 31, 2021 6:03 PM, "Chip Davis" <cdavis(a)codeweavers.com> wrote:
>
Chip
Aug. 31, 2021
Re: [PATCH 4/5] d3d10/effect: Support stream output declaration when creating geometry shaders.
by Matteo Bruni
On Tue, Aug 31, 2021 at 3:57 PM Nikolay Sivov <nsivov(a)codeweavers.com> wrote:
>
>
>
> On 8/31/21 4:32 PM, Matteo Bruni wrote:
> > On Mon, Aug 30, 2021 at 7:07 AM Nikolay Sivov <nsivov(a)codeweavers.com> wrote:
> >> Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
> >> ---
> >> dlls/d3d10/effect.c | 172 ++++++++++++++++++++++++++++++++++++++++++--
> >> 1 file changed, 166 insertions(+), 6 deletions(-)
> > Patch is okay, a few notes below.
> >
> >> diff --git a/dlls/d3d10/effect.c b/dlls/d3d10/effect.c
> >> index 113125e9cbd..c3c98a0da31 100644
> >> --- a/dlls/d3d10/effect.c
> >> +++ b/dlls/d3d10/effect.c
> >> @@ -566,6 +592,127 @@ static HRESULT get_fx10_shader_resources(struct d3d10_effect_variable *v, const
> >> return S_OK;
> >> }
> >>
> >> +struct d3d10_effect_so_decl
> >> +{
> >> + D3D10_SO_DECLARATION_ENTRY *entries;
> >> + SIZE_T capacity;
> >> + SIZE_T count;
> >> + unsigned int stride;
> >> + char *decl;
> >> +};
> >> +
> >> +static void d3d10_effect_cleanup_so_decl(struct d3d10_effect_so_decl *so_decl)
> >> +{
> >> + heap_free(so_decl->entries);
> >> + heap_free(so_decl->decl);
> >> + memset(so_decl, 0, sizeof(*so_decl));
> >> +}
> >> +
> >> +static HRESULT d3d10_effect_parse_stream_output_declaration(const char *decl,
> >> + struct d3d10_effect_so_decl *so_decl)
> >> +{
> >> + static const char * allmask = "xyzw";
> > Usually in HLSL you can use "rgba" in place of "xyzw" for swizzles /
> > writemasks, it might be worth checking if those also work (and are
> > passed through to the effect bytecode unchanged).
> Yes, "rgba" also works apparently. Compiler preserves string as is, does
> not convert to coordinate mask names. I'll add a test for that.
> >
> >> + char *p, *ptr, *end, *next, *mask, *m, *slot;
> >> + unsigned int len = strlen(decl);
> >> + D3D10_SO_DECLARATION_ENTRY e;
> >> +
> >> + memset(so_decl, 0, sizeof(*so_decl));
> >> +
> >> + if (!(so_decl->decl = heap_alloc(len + 1)))
> >> + return E_OUTOFMEMORY;
> >> + memcpy(so_decl->decl, decl, len + 1);
> >> +
> >> + p = so_decl->decl;
> > I think it would be nice to have a small comment showing the expected
> > syntax of a stream out declaration (entry) somewhere around here. Just
> > something to quickly glance at while reading the following code.
> Okay.
> >
> >> +
> >> + while (p && *p)
> >> + {
> >> + memset(&e, 0, sizeof(e));
> >> +
> >> + end = strchr(p, ';');
> >> + next = end ? end + 1 : p + strlen(p);
> >> +
> >> + len = next - p;
> >> + if (end) len--;
> >> +
> >> + /* Remove leading and trailing spaces. */
> >> + while (len && isspace(*p)) { len--; p++; }
> >> + while (len && isspace(p[len - 1])) len--;
> >> +
> >> + p[len] = 0;
> >> +
> >> + /* Output slot */
> >> + if ((slot = strchr(p, ':')))
> >> + {
> >> + *slot = 0;
> >> +
> >> + ptr = p;
> >> + while (*ptr)
> >> + {
> >> + if (!isdigit(*ptr))
> >> + {
> >> + WARN("Invalid output slot %s.\n", debugstr_a(p));
> >> + goto failed;
> >> + }
> >> + ptr++;
> >> + }
> >> +
> >> + e.OutputSlot = atoi(p);
> >> + p = slot + 1;
> >> + }
> >> +
> >> + /* Mask */
> >> + if ((mask = strchr(p, '.')))
> >> + {
> >> + *mask = 0; mask++;
> >> +
> >> + if (!(m = strstr(allmask, mask)))
> >> + {
> >> + WARN("Invalid component mask %s.\n", debugstr_a(mask));
> >> + goto failed;
> >> + }
> >> +
> >> + e.StartComponent = m - allmask;
> >> + e.ComponentCount = strlen(mask);
> > Did you verify that it's illegal to have a wrongly ordered mask (e.g.
> > something like .wzyx)?
> > I expect that to be invalid but better to be sure.
> > Likewise for other assumptions involved here, like repeating the same
> > component twice.
> Yes, it is disallowed to break the order. API manifestation is that you
> specify start and count, which assumes it's always forward looking.
> Regarding error, it won't pass compiler check first, complaining about
> "invalid mask declaration". As far as I can tell that's the only thing
> that compiler checks in this string, you can have non-existent semantics
> as much as you like. That will break effect creation later though,
> presumably because shader object can't be created with invalid declaration.
Excellent. That should already do the right thing then.
> >
> > In general, some more tests with interesting stream out declarations
> > would be nice. I guess you have more planned after the test in patch
> > 5/5.
> I can think of adding more variations with spaces around, and maybe with
> multiple entries. Do you have other ideas?
Yes, that sounds good. I guess generally trying to exercise all the
edge cases of the parser.
I just noticed that there is probably one case that needs special
handling. From the MS docs:
'There is one special Semantic, labeled "$SKIP" which indicates an
empty semantic, leaving the corresponding memory in the stream out
buffer untouched. The $SKIP semantic cannot have a SemanticIndex, but
can have a Mask.'
It should probably be translated into a declaration entry with NULL
semantic name. See test_stream_output() in d3d10core/tests/d3d10core.c
for a few examples (both valid and not) if you haven't yet.
> >> + }
> >> + else
> >> + {
> >> + e.StartComponent = 0;
> >> + e.ComponentCount = 4;
> >> + }
> >> +
> >> + /* Semantic index and name */
> >> + len = strlen(p);
> >> + while (isdigit(p[len - 1]))
> >> + len--;
> >> +
> >> + if (p[len])
> >> + {
> >> + e.SemanticIndex = atoi(&p[len]);
> >> + p[len] = 0;
> >> + }
> >> +
> >> + e.SemanticName = p;
> >> +
> >> + if (!d3d_array_reserve((void **)&so_decl->entries, &so_decl->capacity, so_decl->count + 1,
> >> + sizeof(*so_decl->entries)))
> >> + goto failed;
> >> +
> >> + so_decl->entries[so_decl->count++] = e;
> >> +
> >> + if (e.OutputSlot == 0)
> >> + so_decl->stride += e.ComponentCount * sizeof(float);
> > This looks weird, but that's probably because the API for
> > ID3D10Device_CreateGeometryShaderWithStreamOutput() is confusing (just
> > one stride for up to 4 output buffers? What does it even mean?) and
> > neither the documentation nor our tests seem to clarify that. Any clue
> > what's supposed to happen with multiple output buffers?
> >
> > FWIW that function's signature makes a lot more sense in d3d11.
> My understanding is that in d3d10 you can specify stride only when you
> use one SO buffer. And if you use multiple buffers runtime will use
> default strides for all. For d3d11 you can set each explicitly.
Somehow I missed the relevant tests in d3d10core.c. It is still weird
but I guess not as mysterious now.
After playing with this a bit, it looks like it's actually more strict
than that: if there is just one buffer you need to pass a non-zero
stride; OTOH when there are multiple buffers you need to pass 0 as
stride. Please double check that it's the case (as I still don't trust
myself a lot on this) and consider sending a fix if necessary.
Aug. 31, 2021
[PATCH 5/5] winemac.drv: Remove now-unused -[WineContentView drawRect:].
by Chip Davis
Signed-off-by: Chip Davis <cdavis(a)codeweavers.com>
---
dlls/winemac.drv/cocoa_window.m | 64 ---------------------------------
1 file changed, 64 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m
index 75fc26bbcf8..f30ea0284a1 100644
--- a/dlls/winemac.drv/cocoa_window.m
+++ b/dlls/winemac.drv/cocoa_window.m
@@ -556,70 +556,6 @@ - (void) viewWillDraw
[pendingGlContexts removeAllObjects];
}
- - (void) drawRect:(NSRect)rect
- {
- WineWindow* window = (WineWindow*)[self window];
-
- if ([window contentView] != self)
- return;
-
- if (window.surface && window.surface_mutex &&
- !pthread_mutex_lock(window.surface_mutex))
- {
- const CGRect* rects;
- int count;
-
- if (get_surface_blit_rects(window.surface, &rects, &count))
- {
- CGRect dirtyRect = cgrect_win_from_mac(NSRectToCGRect(rect));
- NSAffineTransform* xform = [NSAffineTransform transform];
- CGContextRef context;
- int i;
-
- [xform translateXBy:0.0 yBy:self.bounds.size.height];
- [xform scaleXBy:1.0 yBy:-1.0];
- [xform concat];
-
- context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
- CGContextSetBlendMode(context, kCGBlendModeCopy);
- CGContextSetInterpolationQuality(context, retina_on ? kCGInterpolationHigh : kCGInterpolationNone);
-
- for (i = 0; i < count; i++)
- {
- CGRect imageRect;
- CGImageRef image;
-
- imageRect = CGRectIntersection(rects[i], dirtyRect);
- image = create_surface_image(window.surface, &imageRect, FALSE, window.colorKeyed,
- window.colorKeyRed, window.colorKeyGreen, window.colorKeyBlue);
-
- if (image)
- {
- // Account for the flipped coordinate system.
- imageRect = cgrect_mac_from_win(imageRect);
- imageRect.origin.y = self.bounds.size.height - imageRect.origin.y - imageRect.size.height;
- CGContextDrawImage(context, imageRect, image);
-
- CGImageRelease(image);
- }
- }
-
- [window windowDidDrawContent];
- }
-
- pthread_mutex_unlock(window.surface_mutex);
- }
-
- // If the window may be transparent, then we have to invalidate the
- // shadow every time we draw. Also, if this is the first time we've
- // drawn since changing from transparent to opaque.
- if (window.drawnSinceShown && (window.colorKeyed || window.usePerPixelAlpha || window.shapeChangedSinceLastDraw))
- {
- window.shapeChangedSinceLastDraw = FALSE;
- [window invalidateShadow];
- }
- }
-
- (void) addGLContext:(WineOpenGLContext*)context
{
BOOL hadContext = _everHadGLContext;
--
2.33.0
Aug. 31, 2021
[PATCH 4/5] winemac.drv: Set the surface contents directly to the layer.
by Chip Davis
Use a top-down DIB for the surface instead of a bottom-up DIB. This
seems to match better with how Core Graphics expects to receive image
data, and allows us to avoid a transform to flip the surface image.
Unfortunately, it requires us to use a transform to flip the image
in the -drawRect: path. We'll be getting rid of that in the next patch,
though.
Signed-off-by: Chip Davis <cdavis(a)codeweavers.com>
---
dlls/winemac.drv/cocoa_window.m | 86 ++++++++++++++++++++++++++-------
dlls/winemac.drv/macdrv_cocoa.h | 3 +-
dlls/winemac.drv/surface.c | 42 +++++++++++-----
3 files changed, 101 insertions(+), 30 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m
index 3eb8ec20877..75fc26bbcf8 100644
--- a/dlls/winemac.drv/cocoa_window.m
+++ b/dlls/winemac.drv/cocoa_window.m
@@ -491,6 +491,54 @@ - (BOOL) isFlipped
return YES;
}
+ - (BOOL) wantsUpdateLayer
+ {
+ return YES /*!_everHadGLContext*/;
+ }
+
+ - (void) updateLayer
+ {
+ WineWindow* window = (WineWindow*)[self window];
+ CGImageRef image = NULL;
+ CGRect imageRect;
+ CALayer* layer = [self layer];
+
+ if ([window contentView] != self)
+ return;
+
+ if (!window.surface || !window.surface_mutex)
+ return;
+
+ pthread_mutex_lock(window.surface_mutex);
+ if (get_surface_blit_rects(window.surface, NULL, NULL))
+ {
+ imageRect = layer.bounds;
+ imageRect.origin.x *= layer.contentsScale;
+ imageRect.origin.y *= layer.contentsScale;
+ imageRect.size.width *= layer.contentsScale;
+ imageRect.size.height *= layer.contentsScale;
+ image = create_surface_image(window.surface, &imageRect, FALSE, window.colorKeyed,
+ window.colorKeyRed, window.colorKeyGreen, window.colorKeyBlue);
+ }
+ pthread_mutex_unlock(window.surface_mutex);
+
+ if (image)
+ {
+ layer.contents = (id)image;
+ CFRelease(image);
+ [window windowDidDrawContent];
+
+ // If the window may be transparent, then we have to invalidate the
+ // shadow every time we draw. Also, if this is the first time we've
+ // drawn since changing from transparent to opaque.
+ if (window.colorKeyed || window.usePerPixelAlpha || window.shapeChangedSinceLastDraw)
+ {
+ window.shapeChangedSinceLastDraw = FALSE;
+ [window invalidateShadow];
+ }
+ }
+ }
+
- (void) viewWillDraw
{
[super viewWillDraw];
@@ -521,12 +569,17 @@ - (void) drawRect:(NSRect)rect
const CGRect* rects;
int count;
- if (get_surface_blit_rects(window.surface, &rects, &count) && count)
+ if (get_surface_blit_rects(window.surface, &rects, &count))
{
CGRect dirtyRect = cgrect_win_from_mac(NSRectToCGRect(rect));
+ NSAffineTransform* xform = [NSAffineTransform transform];
CGContextRef context;
int i;
+ [xform translateXBy:0.0 yBy:self.bounds.size.height];
+ [xform scaleXBy:1.0 yBy:-1.0];
+ [xform concat];
+
context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
CGContextSetBlendMode(context, kCGBlendModeCopy);
CGContextSetInterpolationQuality(context, retina_on ? kCGInterpolationHigh : kCGInterpolationNone);
@@ -537,25 +590,15 @@ - (void) drawRect:(NSRect)rect
CGImageRef image;
imageRect = CGRectIntersection(rects[i], dirtyRect);
- image = create_surface_image(window.surface, &imageRect, FALSE);
+ image = create_surface_image(window.surface, &imageRect, FALSE, window.colorKeyed,
+ window.colorKeyRed, window.colorKeyGreen, window.colorKeyBlue);
if (image)
{
- if (window.colorKeyed)
- {
- CGImageRef maskedImage;
- CGFloat components[] = { window.colorKeyRed - 0.5, window.colorKeyRed + 0.5,
- window.colorKeyGreen - 0.5, window.colorKeyGreen + 0.5,
- window.colorKeyBlue - 0.5, window.colorKeyBlue + 0.5 };
- maskedImage = CGImageCreateWithMaskingColors(image, components);
- if (maskedImage)
- {
- CGImageRelease(image);
- image = maskedImage;
- }
- }
-
- CGContextDrawImage(context, cgrect_mac_from_win(imageRect), image);
+ // Account for the flipped coordinate system.
+ imageRect = cgrect_mac_from_win(imageRect);
+ imageRect.origin.y = self.bounds.size.height - imageRect.origin.y - imageRect.size.height;
+ CGContextDrawImage(context, imageRect, image);
CGImageRelease(image);
}
@@ -708,6 +751,9 @@ - (void) setRetinaMode:(int)mode
[self updateGLContexts];
_retinaMode = !!mode;
+ [self layer].contentsScale = mode ? 2.0 : 1.0;
+ [self layer].minificationFilter = mode ? kCAFilterLinear : kCAFilterNearest;
+ [self layer].magnificationFilter = mode ? kCAFilterLinear : kCAFilterNearest;
[super setRetinaMode:mode];
}
@@ -1028,6 +1074,9 @@ + (WineWindow*) createWindowWithFeatures:(const struct macdrv_window_features*)w
if (!contentView)
return nil;
[contentView setWantsLayer:YES];
+ [contentView layer].minificationFilter = retina_on ? kCAFilterLinear : kCAFilterNearest;
+ [contentView layer].magnificationFilter = retina_on ? kCAFilterLinear : kCAFilterNearest;
+ [contentView layer].contentsScale = retina_on ? 2.0 : 1.0;
[contentView setAutoresizesSubviews:NO];
/* We use tracking areas in addition to setAcceptsMouseMovedEvents:YES
@@ -3599,6 +3648,9 @@ macdrv_view macdrv_create_view(CGRect rect)
view = [[WineContentView alloc] initWithFrame:NSRectFromCGRect(cgrect_mac_from_win(rect))];
[view setWantsLayer:YES];
+ [view layer].minificationFilter = retina_on ? kCAFilterLinear : kCAFilterNearest;
+ [view layer].magnificationFilter = retina_on ? kCAFilterLinear : kCAFilterNearest;
+ [view layer].contentsScale = retina_on ? 2.0 : 1.0;
[view setAutoresizesSubviews:NO];
[view setAutoresizingMask:NSViewNotSizable];
[view setHidden:YES];
diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h
index b02ad79f025..47ae6627b9f 100644
--- a/dlls/winemac.drv/macdrv_cocoa.h
+++ b/dlls/winemac.drv/macdrv_cocoa.h
@@ -566,7 +566,8 @@ extern void macdrv_order_cocoa_window(macdrv_window w, macdrv_window prev,
extern void macdrv_get_cocoa_window_frame(macdrv_window w, CGRect* out_frame) DECLSPEC_HIDDEN;
extern void macdrv_set_cocoa_parent_window(macdrv_window w, macdrv_window parent) DECLSPEC_HIDDEN;
extern void macdrv_set_window_surface(macdrv_window w, void *surface, pthread_mutex_t *mutex) DECLSPEC_HIDDEN;
-extern CGImageRef create_surface_image(void *window_surface, CGRect *rect, int copy_data) DECLSPEC_HIDDEN;
+extern CGImageRef create_surface_image(void *window_surface, CGRect *rect, int copy_data, int color_keyed,
+ CGFloat key_red, CGFloat key_green, CGFloat key_blue) DECLSPEC_HIDDEN;
extern int get_surface_blit_rects(void *window_surface, const CGRect **rects, int *count) DECLSPEC_HIDDEN;
extern void macdrv_window_needs_display(macdrv_window w, CGRect rect) DECLSPEC_HIDDEN;
extern void macdrv_set_window_shape(macdrv_window w, const CGRect *rects, int count) DECLSPEC_HIDDEN;
diff --git a/dlls/winemac.drv/surface.c b/dlls/winemac.drv/surface.c
index 7be1b6850e0..6a5cd535923 100644
--- a/dlls/winemac.drv/surface.c
+++ b/dlls/winemac.drv/surface.c
@@ -264,7 +264,7 @@ struct window_surface *create_surface(macdrv_window window, const RECT *rect,
surface->info.bmiHeader.biSize = sizeof(surface->info.bmiHeader);
surface->info.bmiHeader.biWidth = width;
- surface->info.bmiHeader.biHeight = height; /* bottom-up */
+ surface->info.bmiHeader.biHeight = -height; /* top-down */
surface->info.bmiHeader.biPlanes = 1;
surface->info.bmiHeader.biBitCount = 32;
surface->info.bmiHeader.biSizeImage = get_dib_image_size(&surface->info);
@@ -342,18 +342,21 @@ int get_surface_blit_rects(void *window_surface, const CGRect **rects, int *coun
{
struct macdrv_window_surface *surface = get_mac_surface(window_surface);
- if (surface->blit_data)
+ if (rects && count)
{
- *rects = (const CGRect*)surface->blit_data->Buffer;
- *count = surface->blit_data->rdh.nCount;
- }
- else
- {
- *rects = NULL;
- *count = 0;
+ if (surface->blit_data)
+ {
+ *rects = (const CGRect*)surface->blit_data->Buffer;
+ *count = surface->blit_data->rdh.nCount;
+ }
+ else
+ {
+ *rects = NULL;
+ *count = 0;
+ }
}
- return (surface->blit_data != NULL);
+ return (surface->blit_data != NULL && surface->blit_data->rdh.nCount > 0);
}
/***********************************************************************
@@ -371,7 +374,8 @@ int get_surface_blit_rects(void *window_surface, const CGRect **rects, int *coun
* must not use Win32 or Wine functions, including debug
* logging.
*/
-CGImageRef create_surface_image(void *window_surface, CGRect *rect, int copy_data)
+CGImageRef create_surface_image(void *window_surface, CGRect *rect, int copy_data, int color_keyed,
+ CGFloat key_red, CGFloat key_green, CGFloat key_blue)
{
CGImageRef cgimage = NULL;
struct macdrv_window_surface *surface = get_mac_surface(window_surface);
@@ -392,7 +396,7 @@ CGImageRef create_surface_image(void *window_surface, CGRect *rect, int copy_dat
colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
bytes_per_row = get_dib_stride(width, 32);
- offset = CGRectGetMinX(visrect) * 4 + (height - CGRectGetMaxY(visrect)) * bytes_per_row;
+ offset = CGRectGetMinX(visrect) * 4 + CGRectGetMinY(visrect) * bytes_per_row;
size = min(CGRectGetHeight(visrect) * bytes_per_row,
surface->info.bmiHeader.biSizeImage - offset);
@@ -412,6 +416,20 @@ CGImageRef create_surface_image(void *window_surface, CGRect *rect, int copy_dat
provider, NULL, retina_on, kCGRenderingIntentDefault);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorspace);
+
+ if (color_keyed)
+ {
+ CGImageRef maskedImage;
+ CGFloat components[] = { key_red - 0.5, key_red + 0.5,
+ key_green - 0.5, key_green + 0.5,
+ key_blue - 0.5, key_blue + 0.5 };
+ maskedImage = CGImageCreateWithMaskingColors(cgimage, components);
+ if (maskedImage)
+ {
+ CGImageRelease(cgimage);
+ cgimage = maskedImage;
+ }
+ }
}
return cgimage;
--
2.33.0
Aug. 31, 2021
[PATCH 3/5] winemac.drv: Move GL context update code to -viewWillDraw method.
by Chip Davis
One of my goals with this series is getting rid of the -drawRect:
method. We shouldn't need it after we start setting surface contents
directly to layers.
Signed-off-by: Chip Davis <cdavis(a)codeweavers.com>
---
dlls/winemac.drv/cocoa_window.m | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m
index 4d7aa570552..3eb8ec20877 100644
--- a/dlls/winemac.drv/cocoa_window.m
+++ b/dlls/winemac.drv/cocoa_window.m
@@ -491,9 +491,9 @@ - (BOOL) isFlipped
return YES;
}
- - (void) drawRect:(NSRect)rect
+ - (void) viewWillDraw
{
- WineWindow* window = (WineWindow*)[self window];
+ [super viewWillDraw];
for (WineOpenGLContext* context in pendingGlContexts)
{
@@ -506,6 +506,11 @@ - (void) drawRect:(NSRect)rect
}
[glContexts addObjectsFromArray:pendingGlContexts];
[pendingGlContexts removeAllObjects];
+ }
+
+ - (void) drawRect:(NSRect)rect
+ {
+ WineWindow* window = (WineWindow*)[self window];
if ([window contentView] != self)
return;
--
2.33.0
Aug. 31, 2021
[PATCH 2/5] winemac.drv: Use a mask layer to support window regions.
by Chip Davis
Signed-off-by: Chip Davis <cdavis(a)codeweavers.com>
---
dlls/winemac.drv/cocoa_window.h | 2 -
dlls/winemac.drv/cocoa_window.m | 89 ++++++++++++++++-----------------
2 files changed, 44 insertions(+), 47 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_window.h b/dlls/winemac.drv/cocoa_window.h
index f9c3902dc36..d04961f8251 100644
--- a/dlls/winemac.drv/cocoa_window.h
+++ b/dlls/winemac.drv/cocoa_window.h
@@ -51,8 +51,6 @@ @interface WineWindow : NSPanel <NSWindowDelegate>
NSRect wineFrame;
NSRect roundedWineFrame;
- NSBezierPath* shape;
- NSData* shapeData;
BOOL shapeChangedSinceLastDraw;
BOOL colorKeyed;
diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m
index bc06a9506ee..4d7aa570552 100644
--- a/dlls/winemac.drv/cocoa_window.m
+++ b/dlls/winemac.drv/cocoa_window.m
@@ -321,6 +321,22 @@ - (BOOL) layer:(CALayer*)layer shouldInheritContentsScale:(CGFloat)newScale from
#endif
+(a)interface CAShapeLayer (WineShapeMaskExtensions)
+
+(a)property(readonly, nonatomic, getter=isEmptyShaped) BOOL emptyShaped;
+
+(a)end
+
+(a)implementation CAShapeLayer (WineShapeMaskExtensions)
+
+ - (BOOL) isEmptyShaped
+ {
+ return CGRectEqualToRect(CGPathGetBoundingBox(self.path), CGRectZero);
+ }
+
+(a)end
+
+
@interface WineBaseView : NSView
@end
@@ -388,8 +404,6 @@ @interface WineWindow ()
@property (nonatomic) void* surface;
@property (nonatomic) pthread_mutex_t* surface_mutex;
-(a)property (copy, nonatomic) NSBezierPath* shape;
-(a)property (copy, nonatomic) NSData* shapeData;
@property (nonatomic) BOOL shapeChangedSinceLastDraw;
@property (readonly, nonatomic) BOOL needsTransparency;
@@ -402,6 +416,8 @@ @interface WineWindow ()
@property (readonly, copy, nonatomic) NSArray* childWineWindows;
+ - (void) setShape:(CGPathRef)newShape;
+
- (void) updateForGLSubviews;
- (BOOL) becameEligibleParentOrChild;
@@ -494,17 +510,6 @@ - (void) drawRect:(NSRect)rect
if ([window contentView] != self)
return;
- if (window.drawnSinceShown && window.shapeChangedSinceLastDraw && window.shape && !window.colorKeyed && !window.usePerPixelAlpha)
- {
- [[NSColor clearColor] setFill];
- NSRectFill(rect);
-
- [window.shape addClip];
-
- [[NSColor windowBackgroundColor] setFill];
- NSRectFill(rect);
- }
-
if (window.surface && window.surface_mutex &&
!pthread_mutex_lock(window.surface_mutex))
{
@@ -517,8 +522,6 @@ - (void) drawRect:(NSRect)rect
CGContextRef context;
int i;
- [window.shape addClip];
-
context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
CGContextSetBlendMode(context, kCGBlendModeCopy);
CGContextSetInterpolationQuality(context, retina_on ? kCGInterpolationHigh : kCGInterpolationNone);
@@ -968,7 +971,7 @@ @implementation WineWindow
@synthesize disabled, noActivate, floating, fullscreen, fakingClose, latentParentWindow, hwnd, queue;
@synthesize drawnSinceShown;
@synthesize surface, surface_mutex;
- @synthesize shape, shapeData, shapeChangedSinceLastDraw;
+ @synthesize shapeChangedSinceLastDraw;
@synthesize colorKeyed, colorKeyRed, colorKeyGreen, colorKeyBlue;
@synthesize usePerPixelAlpha;
@synthesize imeData, commandDone;
@@ -1069,8 +1072,6 @@ - (void) dealloc
[queue release];
[latentChildWindows release];
[latentParentWindow release];
- [shape release];
- [shapeData release];
[super dealloc];
}
@@ -2013,7 +2014,7 @@ - (void) setDisabled:(BOOL)newValue
- (BOOL) needsTransparency
{
- return self.shape || self.colorKeyed || self.usePerPixelAlpha ||
+ return self.contentView.layer.mask || self.colorKeyed || self.usePerPixelAlpha ||
(gl_surface_mode == GL_SURFACE_BEHIND && [(WineContentView*)self.contentView hasGLDescendant]);
}
@@ -2035,22 +2036,27 @@ - (void) checkTransparency
}
}
- - (void) setShape:(NSBezierPath*)newShape
+ - (void) setShape:(CGPathRef)newShape
{
- if (shape == newShape) return;
+ CALayer* layer = [[self contentView] layer];
+ CAShapeLayer* mask = layer.mask;
+ if (CGPathEqualToPath(newShape, mask.path)) return;
- if (shape)
- {
- [[self contentView] setNeedsDisplayInRect:[shape bounds]];
- [shape release];
- }
+ if (newShape && !layer.mask)
+ layer.mask = mask = [CAShapeLayer layer];
+ else if (!newShape)
+ layer.mask = mask = nil;
+
+ if (mask.path)
+ [[self contentView] setNeedsDisplayInRect:NSRectFromCGRect(CGPathGetBoundingBox(mask.path))];
if (newShape)
- [[self contentView] setNeedsDisplayInRect:[newShape bounds]];
+ [[self contentView] setNeedsDisplayInRect:NSRectFromCGRect(CGPathGetBoundingBox(newShape))];
- shape = [newShape copy];
+ mask.path = newShape;
self.shapeChangedSinceLastDraw = TRUE;
[self checkTransparency];
+ [self checkEmptyShaped];
}
- (void) makeFocused:(BOOL)activate
@@ -2247,7 +2253,7 @@ - (void) checkWineDisplayLink
- (BOOL) isEmptyShaped
{
- return (self.shapeData.length == sizeof(CGRectZero) && !memcmp(self.shapeData.bytes, &CGRectZero, sizeof(CGRectZero)));
+ return ([[[self contentView] layer].mask isEmptyShaped]);
}
- (BOOL) canProvideSnapshot
@@ -2650,8 +2656,7 @@ - (void) setRetinaMode:(int)mode
[transform scaleBy:scale];
- if (shape)
- [shape transformUsingAffineTransform:transform];
+ [[self contentView] layer].mask.contentsScale = mode ? 2.0 : 1.0;
for (WineBaseView* subview in [self.contentView subviews])
{
@@ -3456,25 +3461,19 @@ void macdrv_set_window_shape(macdrv_window w, const CGRect *rects, int count)
OnMainThread(^{
if (!rects || !count)
{
- window.shape = nil;
- window.shapeData = nil;
+ [window setShape:NULL];
[window checkEmptyShaped];
}
else
{
- size_t length = sizeof(*rects) * count;
- if (window.shapeData.length != length || memcmp(window.shapeData.bytes, rects, length))
- {
- NSBezierPath* path;
- unsigned int i;
+ CGMutablePathRef path;
+ unsigned int i;
- path = [NSBezierPath bezierPath];
- for (i = 0; i < count; i++)
- [path appendBezierPathWithRect:NSRectFromCGRect(cgrect_mac_from_win(rects[i]))];
- window.shape = path;
- window.shapeData = [NSData dataWithBytes:rects length:length];
- [window checkEmptyShaped];
- }
+ path = CGPathCreateMutable();
+ for (i = 0; i < count; i++)
+ CGPathAddRect(path, NULL, cgrect_mac_from_win(rects[i]));
+ [window setShape:path];
+ CGPathRelease(path);
}
});
--
2.33.0
Aug. 31, 2021
[PATCH 1/5] winemac.drv: Enable layer-backed views.
by Chip Davis
Signed-off-by: Chip Davis <cdavis(a)codeweavers.com>
---
dlls/winemac.drv/cocoa_window.m | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m
index d5434b8a966..bc06a9506ee 100644
--- a/dlls/winemac.drv/cocoa_window.m
+++ b/dlls/winemac.drv/cocoa_window.m
@@ -311,6 +311,16 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
@end
+#ifndef MAC_OS_X_VERSION_10_14
+(a)protocol NSViewLayerContentScaleDelegate <NSObject>
+(a)optional
+
+ - (BOOL) layer:(CALayer*)layer shouldInheritContentsScale:(CGFloat)newScale fromWindow:(NSWindow*)window;
+
+(a)end
+#endif
+
+
@interface WineBaseView : NSView
@end
@@ -327,7 +337,7 @@ - (id) initWithFrame:(NSRect)frame device:(id<MTLDevice>)device;
#endif
-(a)interface WineContentView : WineBaseView <NSTextInputClient>
+(a)interface WineContentView : WineBaseView <NSTextInputClient, NSViewLayerContentScaleDelegate>
{
NSMutableArray* glContexts;
NSMutableArray* pendingGlContexts;
@@ -339,6 +349,7 @@ @interface WineContentView : WineBaseView <NSTextInputClient>
NSMutableAttributedString* markedText;
NSRange markedTextSelection;
+ BOOL _retinaMode;
int backingSize[2];
#ifdef HAVE_METAL_METAL_H
@@ -688,9 +699,15 @@ - (void) setRetinaMode:(int)mode
[self setWantsBestResolutionOpenGLSurface:mode];
[self updateGLContexts];
+ _retinaMode = !!mode;
[super setRetinaMode:mode];
}
+ - (BOOL) layer:(CALayer*)layer shouldInheritContentsScale:(CGFloat)newScale fromWindow:(NSWindow*)window
+ {
+ return (_retinaMode || newScale == 1.0);
+ }
+
- (void) viewDidHide
{
[super viewDidHide];
@@ -1002,6 +1019,7 @@ + (WineWindow*) createWindowWithFeatures:(const struct macdrv_window_features*)w
contentView = [[[WineContentView alloc] initWithFrame:NSZeroRect] autorelease];
if (!contentView)
return nil;
+ [contentView setWantsLayer:YES];
[contentView setAutoresizesSubviews:NO];
/* We use tracking areas in addition to setAcceptsMouseMovedEvents:YES
@@ -3576,6 +3594,7 @@ macdrv_view macdrv_create_view(CGRect rect)
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
view = [[WineContentView alloc] initWithFrame:NSRectFromCGRect(cgrect_mac_from_win(rect))];
+ [view setWantsLayer:YES];
[view setAutoresizesSubviews:NO];
[view setAutoresizingMask:NSViewNotSizable];
[view setHidden:YES];
--
2.33.0
Aug. 31, 2021
Re: [PATCH] kernelbase: Mind OS version in the PE header when reporting OS version.
by Paul Gofman
Eh, I probably missed something but something strange happened to this
patch. I see the message that it is committed, but I don't see it in the
list of new patches in #winehackers and also not in git.
On 8/31/21 23:40, Marvin wrote:
> Thank you for your contribution to Wine!
>
> This is an automated notification to let you know that your patch has
> been reviewed and its status set to "Committed".
>
> This means that your patch has been approved, and committed to the
> main git tree. Congratulations!
Aug. 31, 2021
[PATCH] mscoree: Add a buffer for Mono's debug output.
by Esme Povirk
Signed-off-by: Esme Povirk <esme(a)codeweavers.com>
---
Supersedes 213101
dlls/mscoree/metahost.c | 13 -------
dlls/mscoree/mscoree_main.c | 64 +++++++++++++++++++++++++++++++++-
dlls/mscoree/mscoree_private.h | 2 ++
3 files changed, 65 insertions(+), 14 deletions(-)
diff --git a/dlls/mscoree/metahost.c b/dlls/mscoree/metahost.c
index a272f83020a..c362265cf5d 100644
--- a/dlls/mscoree/metahost.c
+++ b/dlls/mscoree/metahost.c
@@ -137,8 +137,6 @@ static MonoAssembly* CDECL mono_assembly_preload_hook_fn(MonoAssemblyName *aname
static void CDECL mono_shutdown_callback_fn(MonoProfiler *prof);
-static void CDECL mono_print_handler_fn(const char *string, INT is_stdout);
-
static MonoImage* CDECL image_open_module_handle_dummy(HMODULE module_handle,
char* fname, UINT has_entry_point, MonoImageOpenStatus* status)
{
@@ -378,17 +376,6 @@ static void CDECL mono_shutdown_callback_fn(MonoProfiler *prof)
is_mono_shutdown = TRUE;
}
-static void CDECL mono_print_handler_fn(const char *string, INT is_stdout)
-{
- const char *p;
- for (; *string; string = p)
- {
- if ((p = strstr(string, "\n"))) p++;
- else p = string + strlen(string);
- wine_dbg_printf("%.*s", (int)(p - string), string);
- }
-}
-
static HRESULT WINAPI thread_set_fn(void)
{
WARN("stub\n");
diff --git a/dlls/mscoree/mscoree_main.c b/dlls/mscoree/mscoree_main.c
index a4567e96de2..0352b633cc9 100644
--- a/dlls/mscoree/mscoree_main.c
+++ b/dlls/mscoree/mscoree_main.c
@@ -50,6 +50,14 @@
WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
WINE_DECLARE_DEBUG_CHANNEL(winediag);
+struct print_handler_tls
+{
+ int length;
+ char buffer[1018];
+};
+
+static DWORD print_tls_index = TLS_OUT_OF_INDEXES;
+
typedef HRESULT (*fnCreateInstance)(REFIID riid, LPVOID *ppObj);
char *WtoA(LPCWSTR wstr)
@@ -214,6 +222,46 @@ HRESULT WINAPI CorBindToRuntimeHost(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor
return ret;
}
+void CDECL mono_print_handler_fn(const char *string, INT is_stdout)
+{
+ struct print_handler_tls *tls = TlsGetValue(print_tls_index);
+
+ if (!tls)
+ {
+ tls = HeapAlloc(GetProcessHeap(), 0, sizeof(*tls));
+ tls->length = 0;
+ TlsSetValue(print_tls_index, tls);
+ }
+
+ while (*string)
+ {
+ int remaining_buffer = sizeof(tls->buffer) - tls->length;
+ int length = strlen(string);
+ const char *newline = memchr(string, '\n', min(length, remaining_buffer));
+
+ if (newline)
+ {
+ length = newline - string + 1;
+ wine_dbg_printf("%.*s%.*s", tls->length, tls->buffer, length, string);
+ tls->length = 0;
+ string += length;
+ }
+ else if (length > remaining_buffer)
+ {
+ /* this would overflow Wine's debug buffer */
+ wine_dbg_printf("%.*s%.*s\n", tls->length, tls->buffer, remaining_buffer, string);
+ tls->length = 0;
+ string += remaining_buffer;
+ }
+ else
+ {
+ memcpy(tls->buffer + tls->length, string, length);
+ tls->length += length;
+ break;
+ }
+ }
+}
+
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
TRACE("(%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
@@ -222,12 +270,26 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
case DLL_PROCESS_ATTACH:
runtimehost_init();
- DisableThreadLibraryCalls(hinstDLL);
+
+ print_tls_index = TlsAlloc();
+
+ if (print_tls_index == TLS_OUT_OF_INDEXES)
+ return FALSE;
+
+ break;
+ case DLL_THREAD_DETACH:
+ if (print_tls_index != TLS_OUT_OF_INDEXES)
+ HeapFree(GetProcessHeap(), 0, TlsGetValue(print_tls_index));
break;
case DLL_PROCESS_DETACH:
expect_no_runtimes();
if (lpvReserved) break; /* process is terminating */
runtimehost_uninit();
+ if (print_tls_index != TLS_OUT_OF_INDEXES)
+ {
+ HeapFree(GetProcessHeap(), 0, TlsGetValue(print_tls_index));
+ TlsFree(print_tls_index);
+ }
break;
}
return TRUE;
diff --git a/dlls/mscoree/mscoree_private.h b/dlls/mscoree/mscoree_private.h
index c4692b4e656..985cdeff770 100644
--- a/dlls/mscoree/mscoree_private.h
+++ b/dlls/mscoree/mscoree_private.h
@@ -219,4 +219,6 @@ extern HRESULT get_file_from_strongname(WCHAR* stringnameW, WCHAR* assemblies_pa
extern void runtimehost_init(void) DECLSPEC_HIDDEN;
extern void runtimehost_uninit(void) DECLSPEC_HIDDEN;
+extern void CDECL mono_print_handler_fn(const char *string, INT is_stdout) DECLSPEC_HIDDEN;
+
#endif /* __MSCOREE_PRIVATE__ */
--
2.30.2
Aug. 31, 2021
Re: [PATCH] mscoree: Add a buffer for Mono's debug output.
by Esme Povirk (she/they)
Yes, thank you, I'll resend.
On Tue, Aug 31, 2021 at 3:27 PM Zebediah Figura (she/her)
<zfigura(a)codeweavers.com> wrote:
>
> On 8/31/21 3:17 PM, Esme Povirk wrote:
> > Signed-off-by: Esme Povirk <esme(a)codeweavers.com>
> > ---
> > dlls/mscoree/metahost.c | 13 -------
> > dlls/mscoree/mscoree_main.c | 64 +++++++++++++++++++++++++++++++++-
> > dlls/mscoree/mscoree_private.h | 2 ++
> > 3 files changed, 65 insertions(+), 14 deletions(-)
> >
> > diff --git a/dlls/mscoree/metahost.c b/dlls/mscoree/metahost.c
> > index a272f83020a..c362265cf5d 100644
> > --- a/dlls/mscoree/metahost.c
> > +++ b/dlls/mscoree/metahost.c
> > @@ -137,8 +137,6 @@ static MonoAssembly* CDECL mono_assembly_preload_hook_fn(MonoAssemblyName *aname
> >
> > static void CDECL mono_shutdown_callback_fn(MonoProfiler *prof);
> >
> > -static void CDECL mono_print_handler_fn(const char *string, INT is_stdout);
> > -
> > static MonoImage* CDECL image_open_module_handle_dummy(HMODULE module_handle,
> > char* fname, UINT has_entry_point, MonoImageOpenStatus* status)
> > {
> > @@ -378,17 +376,6 @@ static void CDECL mono_shutdown_callback_fn(MonoProfiler *prof)
> > is_mono_shutdown = TRUE;
> > }
> >
> > -static void CDECL mono_print_handler_fn(const char *string, INT is_stdout)
> > -{
> > - const char *p;
> > - for (; *string; string = p)
> > - {
> > - if ((p = strstr(string, "\n"))) p++;
> > - else p = string + strlen(string);
> > - wine_dbg_printf("%.*s", (int)(p - string), string);
> > - }
> > -}
> > -
> > static HRESULT WINAPI thread_set_fn(void)
> > {
> > WARN("stub\n");
> > diff --git a/dlls/mscoree/mscoree_main.c b/dlls/mscoree/mscoree_main.c
> > index a4567e96de2..a268638c879 100644
> > --- a/dlls/mscoree/mscoree_main.c
> > +++ b/dlls/mscoree/mscoree_main.c
> > @@ -50,6 +50,14 @@
> > WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
> > WINE_DECLARE_DEBUG_CHANNEL(winediag);
> >
> > +struct print_handler_tls
> > +{
> > + int length;
> > + char buffer[1018];
> > +};
> > +
> > +DWORD print_tls_index = TLS_OUT_OF_INDEXES;
>
> This should be static, right?
>
> > +
> > typedef HRESULT (*fnCreateInstance)(REFIID riid, LPVOID *ppObj);
> >
> > char *WtoA(LPCWSTR wstr)
> > @@ -214,6 +222,46 @@ HRESULT WINAPI CorBindToRuntimeHost(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor
> > return ret;
> > }
> >
> > +void CDECL mono_print_handler_fn(const char *string, INT is_stdout)
> > +{
> > + struct print_handler_tls *tls = TlsGetValue(print_tls_index);
> > +
> > + if (!tls)
> > + {
> > + tls = HeapAlloc(GetProcessHeap(), 0, sizeof(*tls));
> > + tls->length = 0;
> > + TlsSetValue(print_tls_index, tls);
> > + }
> > +
> > + while (*string)
> > + {
> > + int remaining_buffer = sizeof(tls->buffer) - tls->length;
> > + int length = strlen(string);
> > + const char *newline = memchr(string, '\n', min(length, remaining_buffer));
> > +
> > + if (newline)
> > + {
> > + length = newline - string + 1;
> > + wine_dbg_printf("%.*s%.*s", tls->length, tls->buffer, length, string);
> > + tls->length = 0;
> > + string += length;
> > + }
> > + else if (length > remaining_buffer)
> > + {
> > + /* this would overflow Wine's debug buffer */
> > + wine_dbg_printf("%.*s%.*s\n", tls->length, tls->buffer, remaining_buffer, string);
> > + tls->length = 0;
> > + string += remaining_buffer;
> > + }
> > + else
> > + {
> > + memcpy(tls->buffer + tls->length, string, length);
> > + tls->length += length;
> > + break;
> > + }
> > + }
> > +}
> > +
> > BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
> > {
> > TRACE("(%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
> > @@ -222,12 +270,26 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
> > {
> > case DLL_PROCESS_ATTACH:
> > runtimehost_init();
> > - DisableThreadLibraryCalls(hinstDLL);
> > +
> > + print_tls_index = TlsAlloc();
> > +
> > + if (print_tls_index == TLS_OUT_OF_INDEXES)
> > + return FALSE;
> > +
> > + break;
> > + case DLL_THREAD_DETACH:
> > + if (print_tls_index != TLS_OUT_OF_INDEXES)
> > + HeapFree(GetProcessHeap(), 0, TlsGetValue(print_tls_index));
> > break;
> > case DLL_PROCESS_DETACH:
> > expect_no_runtimes();
> > if (lpvReserved) break; /* process is terminating */
> > runtimehost_uninit();
> > + if (print_tls_index != TLS_OUT_OF_INDEXES)
> > + {
> > + HeapFree(GetProcessHeap(), 0, TlsGetValue(print_tls_index));
> > + TlsFree(print_tls_index);
> > + }
> > break;
> > }
> > return TRUE;
> > diff --git a/dlls/mscoree/mscoree_private.h b/dlls/mscoree/mscoree_private.h
> > index c4692b4e656..106171f8e43 100644
> > --- a/dlls/mscoree/mscoree_private.h
> > +++ b/dlls/mscoree/mscoree_private.h
> > @@ -219,4 +219,6 @@ extern HRESULT get_file_from_strongname(WCHAR* stringnameW, WCHAR* assemblies_pa
> > extern void runtimehost_init(void) DECLSPEC_HIDDEN;
> > extern void runtimehost_uninit(void) DECLSPEC_HIDDEN;
> >
> > +extern void CDECL mono_print_handler_fn(const char *string, INT is_stdout);
>
> ...and this should have DECLSPEC_HIDDEN, right?
>
> > +
> > #endif /* __MSCOREE_PRIVATE__ */
> >
>
Aug. 31, 2021
Re: [PATCH] mscoree: Add a buffer for Mono's debug output.
by Zebediah Figura (she/her)
On 8/31/21 3:17 PM, Esme Povirk wrote:
> Signed-off-by: Esme Povirk <esme(a)codeweavers.com>
> ---
> dlls/mscoree/metahost.c | 13 -------
> dlls/mscoree/mscoree_main.c | 64 +++++++++++++++++++++++++++++++++-
> dlls/mscoree/mscoree_private.h | 2 ++
> 3 files changed, 65 insertions(+), 14 deletions(-)
>
> diff --git a/dlls/mscoree/metahost.c b/dlls/mscoree/metahost.c
> index a272f83020a..c362265cf5d 100644
> --- a/dlls/mscoree/metahost.c
> +++ b/dlls/mscoree/metahost.c
> @@ -137,8 +137,6 @@ static MonoAssembly* CDECL mono_assembly_preload_hook_fn(MonoAssemblyName *aname
>
> static void CDECL mono_shutdown_callback_fn(MonoProfiler *prof);
>
> -static void CDECL mono_print_handler_fn(const char *string, INT is_stdout);
> -
> static MonoImage* CDECL image_open_module_handle_dummy(HMODULE module_handle,
> char* fname, UINT has_entry_point, MonoImageOpenStatus* status)
> {
> @@ -378,17 +376,6 @@ static void CDECL mono_shutdown_callback_fn(MonoProfiler *prof)
> is_mono_shutdown = TRUE;
> }
>
> -static void CDECL mono_print_handler_fn(const char *string, INT is_stdout)
> -{
> - const char *p;
> - for (; *string; string = p)
> - {
> - if ((p = strstr(string, "\n"))) p++;
> - else p = string + strlen(string);
> - wine_dbg_printf("%.*s", (int)(p - string), string);
> - }
> -}
> -
> static HRESULT WINAPI thread_set_fn(void)
> {
> WARN("stub\n");
> diff --git a/dlls/mscoree/mscoree_main.c b/dlls/mscoree/mscoree_main.c
> index a4567e96de2..a268638c879 100644
> --- a/dlls/mscoree/mscoree_main.c
> +++ b/dlls/mscoree/mscoree_main.c
> @@ -50,6 +50,14 @@
> WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
> WINE_DECLARE_DEBUG_CHANNEL(winediag);
>
> +struct print_handler_tls
> +{
> + int length;
> + char buffer[1018];
> +};
> +
> +DWORD print_tls_index = TLS_OUT_OF_INDEXES;
This should be static, right?
> +
> typedef HRESULT (*fnCreateInstance)(REFIID riid, LPVOID *ppObj);
>
> char *WtoA(LPCWSTR wstr)
> @@ -214,6 +222,46 @@ HRESULT WINAPI CorBindToRuntimeHost(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor
> return ret;
> }
>
> +void CDECL mono_print_handler_fn(const char *string, INT is_stdout)
> +{
> + struct print_handler_tls *tls = TlsGetValue(print_tls_index);
> +
> + if (!tls)
> + {
> + tls = HeapAlloc(GetProcessHeap(), 0, sizeof(*tls));
> + tls->length = 0;
> + TlsSetValue(print_tls_index, tls);
> + }
> +
> + while (*string)
> + {
> + int remaining_buffer = sizeof(tls->buffer) - tls->length;
> + int length = strlen(string);
> + const char *newline = memchr(string, '\n', min(length, remaining_buffer));
> +
> + if (newline)
> + {
> + length = newline - string + 1;
> + wine_dbg_printf("%.*s%.*s", tls->length, tls->buffer, length, string);
> + tls->length = 0;
> + string += length;
> + }
> + else if (length > remaining_buffer)
> + {
> + /* this would overflow Wine's debug buffer */
> + wine_dbg_printf("%.*s%.*s\n", tls->length, tls->buffer, remaining_buffer, string);
> + tls->length = 0;
> + string += remaining_buffer;
> + }
> + else
> + {
> + memcpy(tls->buffer + tls->length, string, length);
> + tls->length += length;
> + break;
> + }
> + }
> +}
> +
> BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
> {
> TRACE("(%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
> @@ -222,12 +270,26 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
> {
> case DLL_PROCESS_ATTACH:
> runtimehost_init();
> - DisableThreadLibraryCalls(hinstDLL);
> +
> + print_tls_index = TlsAlloc();
> +
> + if (print_tls_index == TLS_OUT_OF_INDEXES)
> + return FALSE;
> +
> + break;
> + case DLL_THREAD_DETACH:
> + if (print_tls_index != TLS_OUT_OF_INDEXES)
> + HeapFree(GetProcessHeap(), 0, TlsGetValue(print_tls_index));
> break;
> case DLL_PROCESS_DETACH:
> expect_no_runtimes();
> if (lpvReserved) break; /* process is terminating */
> runtimehost_uninit();
> + if (print_tls_index != TLS_OUT_OF_INDEXES)
> + {
> + HeapFree(GetProcessHeap(), 0, TlsGetValue(print_tls_index));
> + TlsFree(print_tls_index);
> + }
> break;
> }
> return TRUE;
> diff --git a/dlls/mscoree/mscoree_private.h b/dlls/mscoree/mscoree_private.h
> index c4692b4e656..106171f8e43 100644
> --- a/dlls/mscoree/mscoree_private.h
> +++ b/dlls/mscoree/mscoree_private.h
> @@ -219,4 +219,6 @@ extern HRESULT get_file_from_strongname(WCHAR* stringnameW, WCHAR* assemblies_pa
> extern void runtimehost_init(void) DECLSPEC_HIDDEN;
> extern void runtimehost_uninit(void) DECLSPEC_HIDDEN;
>
> +extern void CDECL mono_print_handler_fn(const char *string, INT is_stdout);
...and this should have DECLSPEC_HIDDEN, right?
> +
> #endif /* __MSCOREE_PRIVATE__ */
>
Aug. 31, 2021
[PATCH] mscoree: Add a buffer for Mono's debug output.
by Esme Povirk
Signed-off-by: Esme Povirk <esme(a)codeweavers.com>
---
dlls/mscoree/metahost.c | 13 -------
dlls/mscoree/mscoree_main.c | 64 +++++++++++++++++++++++++++++++++-
dlls/mscoree/mscoree_private.h | 2 ++
3 files changed, 65 insertions(+), 14 deletions(-)
diff --git a/dlls/mscoree/metahost.c b/dlls/mscoree/metahost.c
index a272f83020a..c362265cf5d 100644
--- a/dlls/mscoree/metahost.c
+++ b/dlls/mscoree/metahost.c
@@ -137,8 +137,6 @@ static MonoAssembly* CDECL mono_assembly_preload_hook_fn(MonoAssemblyName *aname
static void CDECL mono_shutdown_callback_fn(MonoProfiler *prof);
-static void CDECL mono_print_handler_fn(const char *string, INT is_stdout);
-
static MonoImage* CDECL image_open_module_handle_dummy(HMODULE module_handle,
char* fname, UINT has_entry_point, MonoImageOpenStatus* status)
{
@@ -378,17 +376,6 @@ static void CDECL mono_shutdown_callback_fn(MonoProfiler *prof)
is_mono_shutdown = TRUE;
}
-static void CDECL mono_print_handler_fn(const char *string, INT is_stdout)
-{
- const char *p;
- for (; *string; string = p)
- {
- if ((p = strstr(string, "\n"))) p++;
- else p = string + strlen(string);
- wine_dbg_printf("%.*s", (int)(p - string), string);
- }
-}
-
static HRESULT WINAPI thread_set_fn(void)
{
WARN("stub\n");
diff --git a/dlls/mscoree/mscoree_main.c b/dlls/mscoree/mscoree_main.c
index a4567e96de2..a268638c879 100644
--- a/dlls/mscoree/mscoree_main.c
+++ b/dlls/mscoree/mscoree_main.c
@@ -50,6 +50,14 @@
WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
WINE_DECLARE_DEBUG_CHANNEL(winediag);
+struct print_handler_tls
+{
+ int length;
+ char buffer[1018];
+};
+
+DWORD print_tls_index = TLS_OUT_OF_INDEXES;
+
typedef HRESULT (*fnCreateInstance)(REFIID riid, LPVOID *ppObj);
char *WtoA(LPCWSTR wstr)
@@ -214,6 +222,46 @@ HRESULT WINAPI CorBindToRuntimeHost(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor
return ret;
}
+void CDECL mono_print_handler_fn(const char *string, INT is_stdout)
+{
+ struct print_handler_tls *tls = TlsGetValue(print_tls_index);
+
+ if (!tls)
+ {
+ tls = HeapAlloc(GetProcessHeap(), 0, sizeof(*tls));
+ tls->length = 0;
+ TlsSetValue(print_tls_index, tls);
+ }
+
+ while (*string)
+ {
+ int remaining_buffer = sizeof(tls->buffer) - tls->length;
+ int length = strlen(string);
+ const char *newline = memchr(string, '\n', min(length, remaining_buffer));
+
+ if (newline)
+ {
+ length = newline - string + 1;
+ wine_dbg_printf("%.*s%.*s", tls->length, tls->buffer, length, string);
+ tls->length = 0;
+ string += length;
+ }
+ else if (length > remaining_buffer)
+ {
+ /* this would overflow Wine's debug buffer */
+ wine_dbg_printf("%.*s%.*s\n", tls->length, tls->buffer, remaining_buffer, string);
+ tls->length = 0;
+ string += remaining_buffer;
+ }
+ else
+ {
+ memcpy(tls->buffer + tls->length, string, length);
+ tls->length += length;
+ break;
+ }
+ }
+}
+
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
TRACE("(%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
@@ -222,12 +270,26 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
case DLL_PROCESS_ATTACH:
runtimehost_init();
- DisableThreadLibraryCalls(hinstDLL);
+
+ print_tls_index = TlsAlloc();
+
+ if (print_tls_index == TLS_OUT_OF_INDEXES)
+ return FALSE;
+
+ break;
+ case DLL_THREAD_DETACH:
+ if (print_tls_index != TLS_OUT_OF_INDEXES)
+ HeapFree(GetProcessHeap(), 0, TlsGetValue(print_tls_index));
break;
case DLL_PROCESS_DETACH:
expect_no_runtimes();
if (lpvReserved) break; /* process is terminating */
runtimehost_uninit();
+ if (print_tls_index != TLS_OUT_OF_INDEXES)
+ {
+ HeapFree(GetProcessHeap(), 0, TlsGetValue(print_tls_index));
+ TlsFree(print_tls_index);
+ }
break;
}
return TRUE;
diff --git a/dlls/mscoree/mscoree_private.h b/dlls/mscoree/mscoree_private.h
index c4692b4e656..106171f8e43 100644
--- a/dlls/mscoree/mscoree_private.h
+++ b/dlls/mscoree/mscoree_private.h
@@ -219,4 +219,6 @@ extern HRESULT get_file_from_strongname(WCHAR* stringnameW, WCHAR* assemblies_pa
extern void runtimehost_init(void) DECLSPEC_HIDDEN;
extern void runtimehost_uninit(void) DECLSPEC_HIDDEN;
+extern void CDECL mono_print_handler_fn(const char *string, INT is_stdout);
+
#endif /* __MSCOREE_PRIVATE__ */
--
2.30.2
Aug. 31, 2021
Re: RFC: Reparse Point/NT Symlink Support [3]
by Erich E. Hoover
On Tue, Aug 31, 2021 at 11:11 AM Zebediah Figura (she/her)
<zfigura(a)codeweavers.com> wrote:
> ...
> Doesn't this end up being a problem regardless of how we store symlinks
> internally, though? As far as I can tell, all of this logic should
> happen on the PE side.
When we let the OS handle symlinks for us then everything seems to
work properly, though it's possible that I've missed something.
Best,
Erich
Aug. 31, 2021
Re: [RFC PATCH 0/5] XAudio PE conversion.
by Alexandre Julliard
"Zebediah Figura (she/her)" <zfigura(a)codeweavers.com> writes:
> On 8/31/21 1:25 PM, Alexandre Julliard wrote:
>> "Zebediah Figura (she/her)" <zfigura(a)codeweavers.com> writes:
>>
>>> (3) Most importantly, I would like to coöperate with distributions. As
>>> I understand, they already don't like the way we distribute wine-mono
>>> and wine-gecko, and I don't think we should annoy them any further by
>>> going behind their back and distributing more pre-built libraries.
>>>
>>> I know people here think that they won't want to distribute PE
>>> libraries, but I'm inclined to think that at least some distributions
>>> won't be happy with our proposed solution either. See [1] [2] [3] [4]
>>> for popular distributions trying to discourage source imports and
>>> static libraries. I get that we're a special case, and maybe
>>> distributions will think so too, but I really want to again argue that
>>> we shouldn't be making that decision for them.
>> Have you tried asking them?
>
> I haven't yet. I didn't really want to speak on behalf of the Wine
> project if the consensus was against consulting them, and I didn't
> want to start that conversation without the possibility that its
> fruits would at least be taken into account. But if there are no
> objections I'll start writing some mails.
I don't see any harm in asking. I'll admit that I'm fairly skeptical, so
it will be up to you to build a convincing case. Getting the buy-in of
the major distros is obviously a required step.
>> Remember that we need the libs to have custom names, to avoid conflicts
>> with Windows apps shipping the same libs.
>
> Yep, I've been keeping that in mind. If we want to distribute shared
> libraries I'm inclined to think the best solution there is to copy (or
> symlink, or fake-symlink) them into the prefix with different names.
This won't work for nested dependencies. For instance the PE libpng is
going to import the PE zlib, so it needs to have been renamed at build
time already.
--
Alexandre Julliard
julliard(a)winehq.org
Aug. 31, 2021
Re: [RFC PATCH 0/5] XAudio PE conversion.
by Zebediah Figura (she/her)
On 8/31/21 1:25 PM, Alexandre Julliard wrote:
> "Zebediah Figura (she/her)" <zfigura(a)codeweavers.com> writes:
>
>> (3) Most importantly, I would like to coöperate with distributions. As
>> I understand, they already don't like the way we distribute wine-mono
>> and wine-gecko, and I don't think we should annoy them any further by
>> going behind their back and distributing more pre-built libraries.
>>
>> I know people here think that they won't want to distribute PE
>> libraries, but I'm inclined to think that at least some distributions
>> won't be happy with our proposed solution either. See [1] [2] [3] [4]
>> for popular distributions trying to discourage source imports and
>> static libraries. I get that we're a special case, and maybe
>> distributions will think so too, but I really want to again argue that
>> we shouldn't be making that decision for them.
>
> Have you tried asking them?
I haven't yet. I didn't really want to speak on behalf of the Wine
project if the consensus was against consulting them, and I didn't want
to start that conversation without the possibility that its fruits would
at least be taken into account. But if there are no objections I'll
start writing some mails.
> Remember that we need the libs to have custom names, to avoid conflicts
> with Windows apps shipping the same libs.
Yep, I've been keeping that in mind. If we want to distribute shared
libraries I'm inclined to think the best solution there is to copy (or
symlink, or fake-symlink) them into the prefix with different names.
Aug. 31, 2021
Re: [RFC PATCH 0/5] XAudio PE conversion.
by Rémi Bernon
On 8/31/21 8:06 PM, Zebediah Figura (she/her) wrote:
> (1) I really don't want to have to build any libraries that aren't part
> of Wine. More importantly, I don't want anyone who's not a regular Wine
> developer to ever have to build any libraries that aren't part of Wine.
> Also, if I do need to build (say) libvkd3d-shader, I want to *only* have
> to build libvkd3d-shader and not all of the Wine dependencies at once.
>
> This is quite likely the only thing that holds me back from contributing
> to wine-mono (not that this is entirely Esme's fault; the problem
> affects mono upstream, although wine-mono has doubled down on it)
>
(Well, things like zlib is clearly not part of Wine, but TBH I don't
really see how vkd3d is not a part of Wine.)
With the PoC you could already be working on the dependencies sources in
the "wine-ext" umbrella project, building whichever Wine module depends
on it to test it. If you don't need to build any Wine module to test it,
then just build the project with its own build system.
Then, having a separate umbrella project has its drawbacks and I agree
with Alexandre here that it makes bisection inconvenient. But even if we
consider having the sources included in Wine you could very well have a
configure flag to point to an alternate source location, while still
using Wine makefiles to build the corresponding Wine module.
> (2) I would like bisecting dependencies to not be a pain. As someone who
> will be working on vkd3d a lot, this is quite important to me. Ideally
> this means that the dependencies should exist in shared libraries, not
> static ones.
>
> I would also like to be able to develop in a separate tree, since git
> submodules are terrible for doing active development on a component.
> Rémi's proposed solution does not really allow for that as far as I can
> tell.
>
Anyway, I'm not sure vkd3d if was in question here. I mentioned it
previously as an example of external dependencies which I would find
nicer to have integrated with Wine build (alongside with wine-mono and
wine-gecko but they're way beyond reach), but I don't know that we're
planning on any change there.
> As an aside, I still think there is something to be gained in using
> shared libraries to reduce disk space. Almost all of our PE dependencies
> are not only shared across multiple DLLs, but will often be loaded
> multiple times in the same process (vkd3d, faudio, gnutls, libpng, zlib,
> freetype, mpg123 all come immediately to mind. To some degree we can try
> to abstract that out with our own shared-to-static shims, but that takes
> some work which I think is rather unnecessary.)
>
Well, my PoC didn't use shared libraries because it seemed to be the
initially intended way with Jacek idea. However, using Wine makefiles
it's really just a matter of few lines and a specfile to make them DLLs
instead.
> (3) Most importantly, I would like to coöperate with distributions. As I
> understand, they already don't like the way we distribute wine-mono and
> wine-gecko, and I don't think we should annoy them any further by going
> behind their back and distributing more pre-built libraries.
>
I'm sure they dislike the wine-mono / wine-gecko situation more because
we're downloading them separately from an untrusted source rather than
because they embed a lot of already packaged third-party dependencies.
FWIW building them as part of Wine would probably be much appreciated,
regardless of their content.
Cheers,
--
Rémi Bernon <rbernon(a)codeweavers.com>
Aug. 31, 2021