[PATCH 1/2] win32u: Cache GL driver functions in DC.
Paul Gofman
pgofman at codeweavers.com
Fri Jan 21 05:36:03 CST 2022
Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
Runescape calls GL functions (SwapBuffers, glFinish) from different threads.
That mostly goes well except for when the DC is locked by ExtEscape() and the
other thread calls, e. g., SwapBuffers that fails because GL can't get driver
funcs (get_dc_ptr() in__wine_get_wgl_driver() returns NULL as the DC is locked
by the other thread).
I don't see any reason why getting GL funcs should fail in this case. Caching
gl_funcs and using them with get_dc_obj() locking solves this type of race.
dlls/win32u/dc.c | 19 -------------------
dlls/win32u/driver.c | 20 ++++++++++++--------
dlls/win32u/ntgdi_private.h | 21 +++++++++++++++++++++
3 files changed, 33 insertions(+), 27 deletions(-)
diff --git a/dlls/win32u/dc.c b/dlls/win32u/dc.c
index 3aae73779e9..9c09bf66e03 100644
--- a/dlls/win32u/dc.c
+++ b/dlls/win32u/dc.c
@@ -63,25 +63,6 @@ static const struct gdi_obj_funcs dc_funcs =
};
-static inline DC *get_dc_obj( HDC hdc )
-{
- DWORD type;
- DC *dc = get_any_obj_ptr( hdc, &type );
- if (!dc) return NULL;
-
- switch (type)
- {
- case NTGDI_OBJ_DC:
- case NTGDI_OBJ_MEMDC:
- case NTGDI_OBJ_ENHMETADC:
- return dc;
- default:
- GDI_ReleaseObj( hdc );
- SetLastError( ERROR_INVALID_HANDLE );
- return NULL;
- }
-}
-
/* alloc DC_ATTR from a pool of memory accessible from client */
static DC_ATTR *alloc_dc_attr(void)
{
diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c
index 39996086c6d..233427b0964 100644
--- a/dlls/win32u/driver.c
+++ b/dlls/win32u/driver.c
@@ -1347,14 +1347,18 @@ NTSTATUS WINAPI NtGdiDdDDICheckVidPnExclusiveOwnership( const D3DKMT_CHECKVIDPNE
*/
struct opengl_funcs * CDECL __wine_get_wgl_driver( HDC hdc, UINT version )
{
- struct opengl_funcs *ret = NULL;
- DC * dc = get_dc_ptr( hdc );
+ struct opengl_funcs *ret;
+ PHYSDEV physdev;
+ DC * dc;
- if (dc)
- {
- PHYSDEV physdev = GET_DC_PHYSDEV( dc, wine_get_wgl_driver );
- ret = physdev->funcs->wine_get_wgl_driver( physdev, version );
- release_dc_ptr( dc );
- }
+ if (!(dc = get_dc_obj( hdc ))) return NULL;
+ ret = dc->gl_funcs;
+ GDI_ReleaseObj( hdc );
+ if (ret) return ret;
+
+ if (!(dc = get_dc_ptr( hdc ))) return NULL;
+ physdev = GET_DC_PHYSDEV( dc, wine_get_wgl_driver );
+ dc->gl_funcs = ret = physdev->funcs->wine_get_wgl_driver( physdev, version );
+ release_dc_ptr( dc );
return ret;
}
diff --git a/dlls/win32u/ntgdi_private.h b/dlls/win32u/ntgdi_private.h
index bfeb4557da7..54a4dc17eaf 100644
--- a/dlls/win32u/ntgdi_private.h
+++ b/dlls/win32u/ntgdi_private.h
@@ -87,6 +87,8 @@ typedef struct tagDC
XFORM xformVport2World; /* Inverse of the above transformation */
BOOL vport2WorldValid; /* Is xformVport2World valid? */
RECT bounds; /* Current bounding rect */
+
+ struct opengl_funcs *gl_funcs; /* Opengl driver functions */
} DC;
/* Certain functions will do no further processing if the driver returns this.
@@ -660,6 +662,25 @@ static inline void copy_bitmapinfo( BITMAPINFO *dst, const BITMAPINFO *src )
memcpy( dst, src, get_dib_info_size( src, DIB_RGB_COLORS ));
}
+static inline DC *get_dc_obj( HDC hdc )
+{
+ DWORD type;
+ DC *dc = get_any_obj_ptr( hdc, &type );
+ if (!dc) return NULL;
+
+ switch (type)
+ {
+ case NTGDI_OBJ_DC:
+ case NTGDI_OBJ_MEMDC:
+ case NTGDI_OBJ_ENHMETADC:
+ return dc;
+ default:
+ GDI_ReleaseObj( hdc );
+ SetLastError( ERROR_INVALID_HANDLE );
+ return NULL;
+ }
+}
+
extern void CDECL free_heap_bits( struct gdi_image_bits *bits ) DECLSPEC_HIDDEN;
void set_gdi_client_ptr( HGDIOBJ handle, void *ptr ) DECLSPEC_HIDDEN;
--
2.34.1
More information about the wine-devel
mailing list