Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
b030d20f
Commit
b030d20f
authored
Jan 23, 2000
by
Ove Kaaven
Committed by
Alexandre Julliard
Jan 23, 2000
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Supercharged XShm implementation for DirectDraw.
parent
52faa565
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
160 additions
and
42 deletions
+160
-42
ddraw.c
graphics/ddraw.c
+21
-4
x11drv.h
include/x11drv.h
+2
-0
event.c
windows/x11drv/event.c
+137
-38
No files found.
graphics/ddraw.c
View file @
b030d20f
...
...
@@ -737,6 +737,18 @@ static HRESULT WINAPI IDirectDrawSurface4Impl_Lock(
}
else
{
assert
(
This
->
s
.
surface_desc
.
u1
.
lpSurface
);
}
/* wait for any previous operations to complete */
#ifdef HAVE_LIBXXSHM
if
(
This
->
t
.
xlib
.
image
&&
(
SDDSCAPS
(
This
)
&
DDSCAPS_VISIBLE
)
&&
This
->
s
.
ddraw
->
e
.
xlib
.
xshm_active
)
{
/*
int compl = InterlockedExchange( &This->s.ddraw->e.xlib.xshm_compl, 0 );
if (compl) X11DRV_EVENT_WaitShmCompletion( compl );
*/
X11DRV_EVENT_WaitShmCompletions
(
This
->
s
.
ddraw
->
d
.
drawable
);
}
#endif
return
DD_OK
;
}
...
...
@@ -761,10 +773,13 @@ static void Xlib_copy_surface_on_screen(IDirectDrawSurface4Impl* This) {
#ifdef HAVE_LIBXXSHM
if
(
This
->
s
.
ddraw
->
e
.
xlib
.
xshm_active
)
{
int
compl
=
This
->
s
.
ddraw
->
e
.
xlib
.
xshm_compl
;
if
(
compl
)
X11DRV_EVENT_WaitShmCompletion
(
compl
);
This
->
s
.
ddraw
->
e
.
xlib
.
xshm_compl
=
X11DRV_EVENT_PrepareShmCompletion
(
This
->
s
.
ddraw
->
d
.
drawable
);
/*
X11DRV_EVENT_WaitReplaceShmCompletion( &This->s.ddraw->e.xlib.xshm_compl, This->s.ddraw->d.drawable );
*/
/* let WaitShmCompletions track 'em for now */
/* (you may want to track it again whenever you implement DX7's partial surface locking,
where threads have concurrent access) */
X11DRV_EVENT_PrepareShmCompletion
(
This
->
s
.
ddraw
->
d
.
drawable
);
TSXShmPutImage
(
display
,
This
->
s
.
ddraw
->
d
.
drawable
,
DefaultGCOfScreen
(
X11DRV_GetXScreen
()),
...
...
@@ -773,6 +788,8 @@ static void Xlib_copy_surface_on_screen(IDirectDrawSurface4Impl* This) {
This
->
t
.
xlib
.
image
->
width
,
This
->
t
.
xlib
.
image
->
height
,
True
);
/* make sure the image is transferred ASAP */
TSXFlush
(
display
);
}
else
#endif
...
...
include/x11drv.h
View file @
b030d20f
...
...
@@ -479,5 +479,7 @@ extern void X11DRV_WND_DockWindow(struct tagWND *wndPtr);
extern
int
X11DRV_EVENT_PrepareShmCompletion
(
Drawable
dw
);
extern
void
X11DRV_EVENT_WaitShmCompletion
(
int
compl
);
extern
void
X11DRV_EVENT_WaitShmCompletions
(
Drawable
dw
);
extern
void
X11DRV_EVENT_WaitReplaceShmCompletion
(
int
*
compl
,
Drawable
dw
);
#endif
/* __WINE_X11DRV_H */
windows/x11drv/event.c
View file @
b030d20f
...
...
@@ -112,7 +112,7 @@ static void EVENT_UnmapNotify( HWND pWnd, XUnmapEvent *event );
#ifdef HAVE_LIBXXSHM
static
void
EVENT_ShmCompletion
(
XShmCompletionEvent
*
event
);
static
int
ShmCompletionType
;
static
int
Shm
Available
,
Shm
CompletionType
;
extern
int
XShmGetEventBase
(
Display
*
);
/* Missing prototype for function in libXext. */
#endif
...
...
@@ -151,7 +151,10 @@ static BOOL in_transition = FALSE; /* This is not used as for today */
BOOL
X11DRV_EVENT_Init
(
void
)
{
#ifdef HAVE_LIBXXSHM
ShmCompletionType
=
XShmGetEventBase
(
display
)
+
ShmCompletion
;
ShmAvailable
=
XShmQueryExtension
(
display
);
if
(
ShmAvailable
)
{
ShmCompletionType
=
XShmGetEventBase
(
display
)
+
ShmCompletion
;
}
#endif
/* Install the X event processing callback */
...
...
@@ -246,7 +249,7 @@ static void EVENT_ProcessEvent( XEvent *event )
}
#ifdef HAVE_LIBXXSHM
if
(
event
->
type
==
ShmCompletionType
)
{
if
(
ShmAvailable
&&
(
event
->
type
==
ShmCompletionType
)
)
{
EVENT_ShmCompletion
(
(
XShmCompletionEvent
*
)
event
);
return
;
}
...
...
@@ -2002,59 +2005,155 @@ ShmCompletion (waiting for app) waking up on shm_read
(waiting for app) returns
(idle)
*/
typedef
struct
{
Drawable
draw
;
LONG
state
,
waiter
;
HANDLE
sema
;
}
shm_qs
;
/* FIXME: this is not pretty */
static
Drawable
shm_draw
=
0
;
static
HANDLE
shm_event
=
0
,
shm_read
=
0
;
static
HANDLE
shm_read
=
0
;
#define SHM_MAX_Q 4
static
volatile
shm_qs
shm_q
[
SHM_MAX_Q
];
static
void
EVENT_ShmCompletion
(
XShmCompletionEvent
*
event
)
{
int
n
;
TRACE
(
"Got ShmCompletion for drawable %ld (time %ld)
\n
"
,
event
->
drawable
,
GetTickCount
()
);
if
(
event
->
drawable
==
shm_draw
)
{
HANDLE
event
=
shm_event
;
shm_draw
=
0
;
SetEvent
(
event
);
TRACE
(
"Event object triggered
\n
"
);
}
else
ERR
(
"Got ShmCompletion for unknown drawable %ld
\n
"
,
event
->
drawable
);
for
(
n
=
0
;
n
<
SHM_MAX_Q
;
n
++
)
if
((
shm_q
[
n
].
draw
==
event
->
drawable
)
&&
(
shm_q
[
n
].
state
==
0
))
{
HANDLE
sema
=
shm_q
[
n
].
sema
;
if
(
!
InterlockedCompareExchange
((
PVOID
*
)
&
shm_q
[
n
].
state
,
(
PVOID
)
1
,
(
PVOID
)
0
))
{
ReleaseSemaphore
(
sema
,
1
,
NULL
);
TRACE
(
"Signaling ShmCompletion (#%d) (semaphore %x)
\n
"
,
n
,
sema
);
}
return
;
}
ERR
(
"Got ShmCompletion for unknown drawable %ld
\n
"
,
event
->
drawable
);
}
int
X11DRV_EVENT_PrepareShmCompletion
(
Drawable
dw
)
{
if
(
shm_draw
)
{
ERR
(
"Multiple ShmCompletion requests not implemented
\n
"
);
return
0
;
}
TRACE
(
"Preparing ShmCompletion (%d) wait for drawable %ld (time %ld)
\n
"
,
ShmCompletionType
,
dw
,
GetTickCount
()
);
shm_draw
=
dw
;
if
(
!
shm_event
)
/* use manual reset just in case */
shm_event
=
ConvertToGlobalHandle
(
CreateEventA
(
NULL
,
TRUE
,
FALSE
,
NULL
)
);
int
n
;
if
(
!
shm_read
)
shm_read
=
ConvertToGlobalHandle
(
FILE_DupUnixHandle
(
ConnectionNumber
(
display
),
GENERIC_READ
|
SYNCHRONIZE
)
);
return
shm_event
;
for
(
n
=
0
;
n
<
SHM_MAX_Q
;
n
++
)
if
(
!
shm_q
[
n
].
draw
)
if
(
!
InterlockedCompareExchange
((
PVOID
*
)
&
shm_q
[
n
].
draw
,
(
PVOID
)
dw
,
(
PVOID
)
0
))
break
;
if
(
n
>=
SHM_MAX_Q
)
{
ERR
(
"Maximum number of outstanding ShmCompletions exceeded!
\n
"
);
return
0
;
}
shm_q
[
n
].
state
=
0
;
if
(
!
shm_q
[
n
].
sema
)
{
shm_q
[
n
].
sema
=
ConvertToGlobalHandle
(
CreateSemaphoreA
(
NULL
,
0
,
256
,
NULL
)
);
TRACE
(
"Allocated ShmCompletion slots have been increased to %d, new semaphore is %x
\n
"
,
n
+
1
,
shm_q
[
n
].
sema
);
}
TRACE
(
"Prepared ShmCompletion (#%d) wait for drawable %ld (thread %lx) (time %ld)
\n
"
,
n
,
dw
,
GetCurrentThreadId
(),
GetTickCount
()
);
return
n
+
1
;
}
static
void
X11DRV_EVENT_WaitReplaceShmCompletionInternal
(
int
*
compl
,
Drawable
dw
,
int
creat
)
{
int
n
=
*
compl
;
LONG
nn
,
st
;
HANDLE
sema
;
if
((
!
n
)
||
(
creat
&&
(
!
shm_q
[
n
-
1
].
draw
)))
{
nn
=
X11DRV_EVENT_PrepareShmCompletion
(
dw
);
if
(
!
(
n
=
(
LONG
)
InterlockedCompareExchange
((
PVOID
*
)
compl
,
(
PVOID
)
nn
,
(
PVOID
)
n
)))
return
;
/* race for compl lost, clear slot */
shm_q
[
nn
-
1
].
draw
=
0
;
return
;
}
if
(
dw
&&
(
shm_q
[
n
-
1
].
draw
!=
dw
))
{
/* this shouldn't happen with the current ddraw implementation */
FIXME
(
"ShmCompletion replace with different drawable!
\n
"
);
return
;
}
sema
=
shm_q
[
n
-
1
].
sema
;
if
(
!
sema
)
{
/* nothing to wait on (PrepareShmCompletion not done yet?), so probably nothing to wait for */
return
;
}
nn
=
InterlockedExchangeAdd
((
PLONG
)
&
shm_q
[
n
-
1
].
waiter
,
1
);
if
((
!
shm_q
[
n
-
1
].
draw
)
||
(
shm_q
[
n
-
1
].
state
==
2
))
{
/* too late, the wait was just cleared (wait complete) */
TRACE
(
"Wait skip for ShmCompletion (#%d) (thread %lx) (time %ld) (semaphore %x)
\n
"
,
n
-
1
,
GetCurrentThreadId
(),
GetTickCount
(),
sema
);
}
else
{
TRACE
(
"Waiting for ShmCompletion (#%d) (thread %lx) (time %ld) (semaphore %x)
\n
"
,
n
-
1
,
GetCurrentThreadId
(),
GetTickCount
(),
sema
);
if
(
nn
)
{
/* another thread is already waiting, let the primary waiter do the dirty work
* (to avoid TSX critical section contention - that could get really slow) */
WaitForSingleObject
(
sema
,
INFINITE
);
}
else
/* we're primary waiter - first check if it's already triggered */
if
(
WaitForSingleObject
(
sema
,
0
)
!=
WAIT_OBJECT_0
)
{
/* nope, may need to poll X event queue, in case the service thread is blocked */
XEvent
event
;
HANDLE
hnd
[
2
];
hnd
[
0
]
=
sema
;
hnd
[
1
]
=
shm_read
;
do
{
/* check X event queue */
if
(
TSXCheckTypedEvent
(
display
,
ShmCompletionType
,
&
event
))
{
EVENT_ProcessEvent
(
&
event
);
}
}
while
(
WaitForMultipleObjects
(
2
,
hnd
,
FALSE
,
INFINITE
)
>
WAIT_OBJECT_0
);
}
TRACE
(
"Wait complete (thread %lx) (time %ld)
\n
"
,
GetCurrentThreadId
(),
GetTickCount
()
);
/* clear wait */
st
=
InterlockedExchange
(
&
shm_q
[
n
-
1
].
state
,
2
);
if
(
st
!=
2
)
{
/* first waiter to return, release all other waiters */
nn
=
shm_q
[
n
-
1
].
waiter
;
TRACE
(
"Signaling %ld additional ShmCompletion (#%d) waiter(s), semaphore %x
\n
"
,
nn
-
1
,
n
-
1
,
sema
);
ReleaseSemaphore
(
sema
,
nn
-
1
,
NULL
);
}
}
nn
=
InterlockedDecrement
((
LPLONG
)
&
shm_q
[
n
-
1
].
waiter
);
if
(
!
nn
)
{
/* last waiter to return, replace drawable and prepare new wait */
shm_q
[
n
-
1
].
draw
=
dw
;
shm_q
[
n
-
1
].
state
=
0
;
}
}
void
X11DRV_EVENT_WaitReplaceShmCompletion
(
int
*
compl
,
Drawable
dw
)
{
X11DRV_EVENT_WaitReplaceShmCompletionInternal
(
compl
,
dw
,
1
);
}
void
X11DRV_EVENT_WaitShmCompletion
(
int
compl
)
{
if
(
!
compl
)
return
;
TRACE
(
"Waiting for ShmCompletion (%d) (thread %lx) (time %ld)
\n
"
,
ShmCompletionType
,
GetCurrentThreadId
(),
GetTickCount
()
);
/* already triggered? */
if
(
WaitForSingleObject
(
compl
,
0
)
!=
WAIT_OBJECT_0
)
{
/* nope, may need to poll X event queue, in case the service thread is blocked */
XEvent
event
;
HANDLE
hnd
[
2
];
X11DRV_EVENT_WaitReplaceShmCompletionInternal
(
&
compl
,
0
,
0
);
}
hnd
[
0
]
=
compl
;
hnd
[
1
]
=
shm_read
;
do
{
/* check X event queue */
if
(
TSXCheckTypedEvent
(
display
,
ShmCompletionType
,
&
event
))
{
EVENT_ProcessEvent
(
&
event
);
}
}
while
(
WaitForMultipleObjects
(
2
,
hnd
,
FALSE
,
INFINITE
)
>
WAIT_OBJECT_0
);
}
ResetEvent
(
compl
);
/* manual reset */
TRACE
(
"Wait complete (time %ld)
\n
"
,
GetTickCount
()
);
void
X11DRV_EVENT_WaitShmCompletions
(
Drawable
dw
)
{
int
n
;
for
(
n
=
0
;
n
<
SHM_MAX_Q
;
n
++
)
if
(
shm_q
[
n
].
draw
==
dw
)
X11DRV_EVENT_WaitShmCompletion
(
n
+
1
);
}
#endif
/* defined(HAVE_LIBXXSHM) */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment