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
November 2021
- 83 participants
- 2620 messages
[PATCH 3/3] comctl32/button: Add a get_box_rect() helper to calculation box rectangle.
by Zhiyi Zhang
get_box_rect() is introduced so that we don't need to duplicate the check box rectangle calculation
when painting themed check boxes.
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/comctl32/button.c | 130 +++++++++++++++++++++--------------------
1 file changed, 67 insertions(+), 63 deletions(-)
diff --git a/dlls/comctl32/button.c b/dlls/comctl32/button.c
index 2738a4caee5..6a463cb3460 100644
--- a/dlls/comctl32/button.c
+++ b/dlls/comctl32/button.c
@@ -1881,11 +1881,65 @@ static void PB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action )
* Check Box & Radio Button Functions
*/
+/* Get adjusted check box or radio box rectangle */
+static RECT get_box_rect(LONG style, LONG ex_style, const RECT *content_rect,
+ const RECT *label_rect, BOOL has_label, SIZE box_size)
+{
+ RECT rect;
+ int delta;
+
+ rect = *content_rect;
+
+ if (style & BS_LEFTTEXT || ex_style & WS_EX_RIGHT)
+ rect.left = rect.right - box_size.cx;
+ else
+ rect.right = rect.left + box_size.cx;
+
+ /* Adjust box when label is valid */
+ if (has_label)
+ {
+ rect.top = label_rect->top;
+ rect.bottom = label_rect->bottom;
+ }
+
+ /* Box must have the correct height */
+ delta = rect.bottom - rect.top - box_size.cy;
+ if ((style & BS_VCENTER) == BS_TOP)
+ {
+ if (delta <= 0)
+ rect.top -= -delta / 2 + 1;
+
+ rect.bottom = rect.top + box_size.cy;
+ }
+ else if ((style & BS_VCENTER) == BS_BOTTOM)
+ {
+ if (delta <= 0)
+ rect.bottom += -delta / 2 + 1;
+
+ rect.top = rect.bottom - box_size.cy;
+ }
+ else
+ {
+ if (delta > 0)
+ {
+ rect.bottom -= delta / 2 + 1;
+ rect.top = rect.bottom - box_size.cy;
+ }
+ else if (delta < 0)
+ {
+ rect.top -= -delta / 2 + 1;
+ rect.bottom = rect.top + box_size.cy;
+ }
+ }
+
+ return rect;
+}
+
static void CB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action )
{
- RECT rbox, labelRect, imageRect, textRect, client;
+ RECT rbox, labelRect, oldLabelRect, imageRect, textRect, client;
HBRUSH hBrush;
- int delta, text_offset, checkBoxWidth, checkBoxHeight;
+ int text_offset;
UINT dtFlags;
LRESULT cdrf;
HFONT hFont;
@@ -1893,6 +1947,7 @@ static void CB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action )
LONG state = infoPtr->state;
LONG style = GetWindowLongW( infoPtr->hwnd, GWL_STYLE );
LONG ex_style = GetWindowLongW( infoPtr->hwnd, GWL_EXSTYLE );
+ SIZE box_size;
HWND parent;
HRGN hrgn;
@@ -1903,10 +1958,10 @@ static void CB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action )
}
GetClientRect(infoPtr->hwnd, &client);
- rbox = labelRect = client;
+ labelRect = client;
- checkBoxWidth = 12 * GetDpiForWindow( infoPtr->hwnd ) / 96 + 1;
- checkBoxHeight = 12 * GetDpiForWindow( infoPtr->hwnd ) / 96 + 1;
+ box_size.cx = 12 * GetDpiForWindow(infoPtr->hwnd) / 96 + 1;
+ box_size.cy = box_size.cx;
if ((hFont = infoPtr->font)) SelectObject( hDC, hFont );
GetCharWidthW( hDC, '0', '0', &text_offset );
@@ -1920,15 +1975,13 @@ static void CB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action )
hrgn = set_control_clipping( hDC, &client );
if (style & BS_LEFTTEXT || ex_style & WS_EX_RIGHT)
- {
- labelRect.right -= checkBoxWidth + text_offset;
- rbox.left = rbox.right - checkBoxWidth;
- }
+ labelRect.right -= box_size.cx + text_offset;
else
- {
- labelRect.left += checkBoxWidth + text_offset;
- rbox.right = checkBoxWidth;
- }
+ labelRect.left += box_size.cx + text_offset;
+
+ oldLabelRect = labelRect;
+ dtFlags = BUTTON_CalcLayoutRects(infoPtr, hDC, &labelRect, &imageRect, &textRect);
+ rbox = get_box_rect(style, ex_style, &client, &labelRect, dtFlags != (UINT)-1L, box_size);
init_custom_draw(&nmcd, infoPtr, hDC, &client);
@@ -1946,16 +1999,6 @@ static void CB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action )
}
/* Draw label */
- client = labelRect;
- dtFlags = BUTTON_CalcLayoutRects(infoPtr, hDC, &labelRect, &imageRect, &textRect);
-
- /* Only adjust rbox when rtext is valid */
- if (dtFlags != (UINT)-1L)
- {
- rbox.top = labelRect.top;
- rbox.bottom = labelRect.bottom;
- }
-
/* Send paint notifications */
nmcd.dwDrawStage = CDDS_PREPAINT;
cdrf = SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd);
@@ -1977,45 +2020,6 @@ static void CB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action )
if (state & BST_PUSHED) flags |= DFCS_PUSHED;
if (style & WS_DISABLED) flags |= DFCS_INACTIVE;
- /* rbox must have the correct height */
- delta = rbox.bottom - rbox.top - checkBoxHeight;
-
- if ((style & BS_VCENTER) == BS_TOP)
- {
- if (delta > 0)
- rbox.bottom = rbox.top + checkBoxHeight;
- else
- {
- rbox.top -= -delta / 2 + 1;
- rbox.bottom = rbox.top + checkBoxHeight;
- }
- }
- else if ((style & BS_VCENTER) == BS_BOTTOM)
- {
- if (delta > 0)
- rbox.top = rbox.bottom - checkBoxHeight;
- else
- {
- rbox.bottom += -delta / 2 + 1;
- rbox.top = rbox.bottom - checkBoxHeight;
- }
- }
- else /* Default */
- {
- if (delta > 0)
- {
- int ofs = delta / 2;
- rbox.bottom -= ofs + 1;
- rbox.top = rbox.bottom - checkBoxHeight;
- }
- else if (delta < 0)
- {
- int ofs = -delta / 2;
- rbox.top -= ofs + 1;
- rbox.bottom = rbox.top + checkBoxHeight;
- }
- }
-
DrawFrameControl(hDC, &rbox, DFC_BUTTON, flags);
}
@@ -2035,7 +2039,7 @@ static void CB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action )
{
labelRect.left--;
labelRect.right++;
- IntersectRect(&labelRect, &labelRect, &client);
+ IntersectRect(&labelRect, &labelRect, &oldLabelRect);
DrawFocusRect(hDC, &labelRect);
}
--
2.32.0
Nov. 4, 2021
[PATCH 2/3] comctl32/button: Simplify focus rectangle calculation for drawing themed split buttons.
by Zhiyi Zhang
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/comctl32/button.c | 17 ++++-------------
1 file changed, 4 insertions(+), 13 deletions(-)
diff --git a/dlls/comctl32/button.c b/dlls/comctl32/button.c
index 00f42322399..2738a4caee5 100644
--- a/dlls/comctl32/button.c
+++ b/dlls/comctl32/button.c
@@ -2861,7 +2861,7 @@ static void GB_ThemedPaint(HTHEME theme, const BUTTON_INFO *infoPtr, HDC hDC, in
static void SB_ThemedPaint(HTHEME theme, const BUTTON_INFO *infoPtr, HDC hDC, int state, UINT dtFlags, BOOL focused)
{
- RECT rc, content_rect, push_rect, dropdown_rect;
+ RECT rc, content_rect, push_rect, dropdown_rect, focus_rect;
NMCUSTOMDRAW nmcd;
LRESULT cdrf;
HWND parent;
@@ -2889,6 +2889,7 @@ static void SB_ThemedPaint(HTHEME theme, const BUTTON_INFO *infoPtr, HDC hDC, in
{
push_rect = rc;
DrawThemeBackground(theme, hDC, BP_PUSHBUTTON, state, &rc, NULL);
+ GetThemeBackgroundContentRect(theme, hDC, BP_PUSHBUTTON, state, &push_rect, &focus_rect);
}
else
{
@@ -2909,6 +2910,7 @@ static void SB_ThemedPaint(HTHEME theme, const BUTTON_INFO *infoPtr, HDC hDC, in
/* The content rect should be the content area of the push button */
GetThemeBackgroundContentRect(theme, hDC, BP_PUSHBUTTON, state, &push_rect, &content_rect);
+ focus_rect = content_rect;
}
if (cdrf & CDRF_NOTIFYPOSTERASE)
@@ -2951,18 +2953,7 @@ static void SB_ThemedPaint(HTHEME theme, const BUTTON_INFO *infoPtr, HDC hDC, in
}
if (cdrf & CDRF_SKIPPOSTPAINT) return;
- if (focused)
- {
- MARGINS margins;
-
- GetThemeMargins(theme, hDC, BP_PUSHBUTTON, state, TMT_CONTENTMARGINS, NULL, &margins);
-
- push_rect.left += margins.cxLeftWidth;
- push_rect.top += margins.cyTopHeight;
- push_rect.right -= margins.cxRightWidth;
- push_rect.bottom -= margins.cyBottomHeight;
- DrawFocusRect(hDC, &push_rect);
- }
+ if (focused) DrawFocusRect(hDC, &focus_rect);
}
static void CL_ThemedPaint(HTHEME theme, const BUTTON_INFO *infoPtr, HDC hDC, int state, UINT dtFlags, BOOL focused)
--
2.32.0
Nov. 4, 2021
[PATCH 1/3] comctl32/button: Simplify focus rectangle calculation for drawing themed push buttons.
by Zhiyi Zhang
The focus rectangle is the same as the result from GetThemeBackgroundContentRect(). So there is no
need to retrieve content margins and calculate it again.
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/comctl32/button.c | 19 ++++---------------
1 file changed, 4 insertions(+), 15 deletions(-)
diff --git a/dlls/comctl32/button.c b/dlls/comctl32/button.c
index fbe060513d2..00f42322399 100644
--- a/dlls/comctl32/button.c
+++ b/dlls/comctl32/button.c
@@ -2651,7 +2651,7 @@ cleanup:
*/
static void PB_ThemedPaint(HTHEME theme, const BUTTON_INFO *infoPtr, HDC hDC, int state, UINT dtFlags, BOOL focused)
{
- RECT bgRect, textRect;
+ RECT bgRect, textRect, focusRect;
NMCUSTOMDRAW nmcd;
LRESULT cdrf;
HWND parent;
@@ -2661,6 +2661,8 @@ static void PB_ThemedPaint(HTHEME theme, const BUTTON_INFO *infoPtr, HDC hDC, in
GetClientRect(infoPtr->hwnd, &bgRect);
GetThemeBackgroundContentRect(theme, hDC, BP_PUSHBUTTON, state, &bgRect, &textRect);
+ focusRect = textRect;
+
init_custom_draw(&nmcd, infoPtr, hDC, &bgRect);
parent = GetParent(infoPtr->hwnd);
@@ -2698,20 +2700,7 @@ static void PB_ThemedPaint(HTHEME theme, const BUTTON_INFO *infoPtr, HDC hDC, in
}
if (cdrf & CDRF_SKIPPOSTPAINT) return;
- if (focused)
- {
- MARGINS margins;
- RECT focusRect = bgRect;
-
- GetThemeMargins(theme, hDC, BP_PUSHBUTTON, state, TMT_CONTENTMARGINS, NULL, &margins);
-
- focusRect.left += margins.cxLeftWidth;
- focusRect.top += margins.cyTopHeight;
- focusRect.right -= margins.cxRightWidth;
- focusRect.bottom -= margins.cyBottomHeight;
-
- DrawFocusRect( hDC, &focusRect );
- }
+ if (focused) DrawFocusRect(hDC, &focusRect);
}
static void CB_ThemedPaint(HTHEME theme, const BUTTON_INFO *infoPtr, HDC hDC, int state, UINT dtFlags, BOOL focused)
--
2.32.0
Nov. 4, 2021
[PATCH] uxtheme: Fix loading a different theme when theming is on.
by Zhiyi Zhang
When a theme is already active and a user tries to activate another theme,
the new theme configuration should be written to the registry so that it's
still in effect after a wine reboot.
Fix a regression introduced in d290362.
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/uxtheme/system.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/dlls/uxtheme/system.c b/dlls/uxtheme/system.c
index ba579a02edc..bf72baccebb 100644
--- a/dlls/uxtheme/system.c
+++ b/dlls/uxtheme/system.c
@@ -446,10 +446,8 @@ HRESULT UXTHEME_SetActiveTheme(PTHEME_FILE tf)
WARN("Failed to get LoadedBefore: %d\n", GetLastError());
RegCloseKey(hKey);
}
- if (loaded_before)
- return MSSTYLES_SetActiveTheme(tf, FALSE);
- if (ret)
+ if (!loaded_before && ret)
UXTHEME_SaveUnthemedSystemMetrics(&metrics);
}
else {
--
2.32.0
Nov. 4, 2021
[PATCH 2/2] uxtheme: Do not draw parent background when handling WM_CTLCOLORSTATIC for static controls.
by Zhiyi Zhang
SetBkMode(TRANSPARENT) already indicates that the parent background should remain untouched.
Drawing parent background destroys any previous content that applications drawn and some
applications rely on the content being unchanged.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51914
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/comctl32/tests/static.c | 1 -
dlls/uxtheme/dialog.c | 6 +-----
2 files changed, 1 insertion(+), 6 deletions(-)
diff --git a/dlls/comctl32/tests/static.c b/dlls/comctl32/tests/static.c
index 269dfbb49eb..99738f7b513 100644
--- a/dlls/comctl32/tests/static.c
+++ b/dlls/comctl32/tests/static.c
@@ -458,7 +458,6 @@ static void test_WM_CTLCOLORSTATIC(void)
todo_wine_if(todo)
ok(mode == OPAQUE, "Expected mode %#x, got %#x.\n", OPAQUE, mode);
color = GetPixel(dialog_hdc, 40, 40);
- todo_wine_if(todo)
ok(color == 0, "Expected pixel %#x, got %#x.\n", 0, color);
ReleaseDC(child, child_hdc);
diff --git a/dlls/uxtheme/dialog.c b/dlls/uxtheme/dialog.c
index 043346b24e2..a949bfc6579 100644
--- a/dlls/uxtheme/dialog.c
+++ b/dlls/uxtheme/dialog.c
@@ -101,15 +101,11 @@ LRESULT WINAPI UXTHEME_DefDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa
HDC controlDC = (HDC)wParam;
HWND controlWnd = (HWND)lParam;
WCHAR controlClass[32];
- RECT rc;
GetClassNameW (controlWnd, controlClass, ARRAY_SIZE(controlClass));
if (lstrcmpiW (controlClass, WC_STATICW) == 0)
{
- /* Static control - draw parent background and set text to
- * transparent, so it looks right on tab pages. */
- GetClientRect (controlWnd, &rc);
- DrawThemeParentBackground (controlWnd, controlDC, &rc);
+ SetBkColor(controlDC, GetSysColor(COLOR_BTNFACE));
SetBkMode (controlDC, TRANSPARENT);
/* Return NULL brush since we painted the BG already */
--
2.32.0
Nov. 4, 2021
[PATCH 1/2] comctl32/tests: Test WM_CTLCOLORSTATIC for static controls in a themed dialog.
by Zhiyi Zhang
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/comctl32/tests/static.c | 92 ++++++++++++++++++++++++++++++++++++
1 file changed, 92 insertions(+)
diff --git a/dlls/comctl32/tests/static.c b/dlls/comctl32/tests/static.c
index 40a337b97b0..269dfbb49eb 100644
--- a/dlls/comctl32/tests/static.c
+++ b/dlls/comctl32/tests/static.c
@@ -27,6 +27,7 @@
#include "winuser.h"
#include "commctrl.h"
#include "resources.h"
+#include "uxtheme.h"
#include "wine/test.h"
@@ -377,6 +378,96 @@ static void test_STM_SETIMAGE(void)
DeleteEnhMetaFile(emf);
}
+static INT_PTR CALLBACK test_WM_CTLCOLORSTATIC_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
+{
+ static HWND child;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ child = CreateWindowA(WC_STATICA, "child", WS_CHILD | WS_VISIBLE, 0, 0, 50, 50, hwnd,
+ (HMENU)100, 0, NULL);
+ ok(child != NULL, "CreateWindowA failed, error %d.\n", GetLastError());
+ return FALSE;
+
+ case WM_CLOSE:
+ DestroyWindow(child);
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+static void test_WM_CTLCOLORSTATIC(void)
+{
+ HTHEME (WINAPI *pGetWindowTheme)(HTHEME) = NULL;
+ HWND parent, dialog, child;
+ COLORREF color, old_color;
+ HDC child_hdc, dialog_hdc;
+ int mode, old_mode;
+ BOOL todo = FALSE;
+ HMODULE uxtheme;
+ HBRUSH brush;
+
+ struct
+ {
+ DLGTEMPLATE tmplate;
+ WORD menu;
+ WORD class;
+ WORD title;
+ } temp = {{0}};
+
+ parent = CreateWindowA(WC_STATICA, "parent", WS_POPUP | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0,
+ NULL);
+ ok(parent != NULL, "CreateWindowA failed, error %d.\n", GetLastError());
+
+ temp.tmplate.style = WS_CHILD | WS_VISIBLE;
+ temp.tmplate.cx = 80;
+ temp.tmplate.cy = 80;
+ dialog = CreateDialogIndirectParamA(NULL, &temp.tmplate, parent, test_WM_CTLCOLORSTATIC_proc, 0);
+ ok(dialog != NULL, "CreateDialogIndirectParamA failed, error %d.\n", GetLastError());
+ child = GetDlgItem(dialog, 100);
+ ok(child != NULL, "Failed to get child static control, error %d.\n", GetLastError());
+
+ uxtheme = LoadLibraryA("uxtheme.dll");
+ if (uxtheme)
+ {
+ pGetWindowTheme = (void*)GetProcAddress(uxtheme, "GetWindowTheme");
+ if (pGetWindowTheme)
+ todo = !!pGetWindowTheme(dialog);
+ }
+
+ dialog_hdc = GetDC(dialog);
+ child_hdc = GetDC(child);
+ PatBlt(dialog_hdc, 0, 0, 80, 80, BLACKNESS);
+
+ old_mode = SetBkMode(child_hdc, OPAQUE);
+ ok(old_mode != 0, "SetBkMode failed.\n");
+ old_color = SetBkColor(child_hdc, 0xaa5511);
+ ok(old_color != CLR_INVALID, "SetBkColor failed.\n");
+
+ brush = (HBRUSH)SendMessageW(dialog, WM_CTLCOLORSTATIC, (WPARAM)child_hdc, (LPARAM)child);
+ todo_wine_if(todo)
+ ok(brush == GetSysColorBrush(COLOR_BTNFACE), "Expected brush %p, got %p.\n",
+ GetSysColorBrush(COLOR_BTNFACE), brush);
+ color = SetBkColor(child_hdc, old_color);
+ ok(color == GetSysColor(COLOR_BTNFACE), "Expected background color %#x, got %#x.\n",
+ GetSysColor(COLOR_BTNFACE), color);
+ mode = SetBkMode(child_hdc, old_mode);
+ todo_wine_if(todo)
+ ok(mode == OPAQUE, "Expected mode %#x, got %#x.\n", OPAQUE, mode);
+ color = GetPixel(dialog_hdc, 40, 40);
+ todo_wine_if(todo)
+ ok(color == 0, "Expected pixel %#x, got %#x.\n", 0, color);
+
+ ReleaseDC(child, child_hdc);
+ ReleaseDC(dialog, dialog_hdc);
+ EndDialog(dialog, 0);
+ DestroyWindow(parent);
+ FreeLibrary(uxtheme);
+}
+
START_TEST(static)
{
static const char classname[] = "testclass";
@@ -417,6 +508,7 @@ START_TEST(static)
test_set_text();
test_set_image();
test_STM_SETIMAGE();
+ test_WM_CTLCOLORSTATIC();
DestroyWindow(hMainWnd);
--
2.32.0
Nov. 4, 2021
[PATCH v2 7/7] wined3d: Try to allocate new Vulkan BOs from the client thread for DISCARD maps.
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/wined3d/adapter_gl.c | 7 ++++
dlls/wined3d/adapter_vk.c | 49 +++++++++++++++++++++++++
dlls/wined3d/buffer.c | 65 ++++++++++++++++++++++++++++++++--
dlls/wined3d/cs.c | 16 ++++++++-
dlls/wined3d/directx.c | 7 ++++
dlls/wined3d/wined3d_private.h | 18 ++++++++++
6 files changed, 159 insertions(+), 3 deletions(-)
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c
index f1cdbffe718..37f055662ea 100644
--- a/dlls/wined3d/adapter_gl.c
+++ b/dlls/wined3d/adapter_gl.c
@@ -4604,6 +4604,12 @@ static void adapter_gl_flush_bo_address(struct wined3d_context *context,
wined3d_context_gl_flush_bo_address(wined3d_context_gl(context), data, size);
}
+static bool adapter_gl_alloc_bo(struct wined3d_device *device, struct wined3d_resource *resource,
+ unsigned int sub_resource_idx, struct wined3d_bo_address *addr)
+{
+ return false;
+}
+
static HRESULT adapter_gl_create_swapchain(struct wined3d_device *device,
struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent,
void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain)
@@ -5057,6 +5063,7 @@ static const struct wined3d_adapter_ops wined3d_adapter_gl_ops =
.adapter_unmap_bo_address = adapter_gl_unmap_bo_address,
.adapter_copy_bo_address = adapter_gl_copy_bo_address,
.adapter_flush_bo_address = adapter_gl_flush_bo_address,
+ .adapter_alloc_bo = adapter_gl_alloc_bo,
.adapter_create_swapchain = adapter_gl_create_swapchain,
.adapter_destroy_swapchain = adapter_gl_destroy_swapchain,
.adapter_create_buffer = adapter_gl_create_buffer,
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c
index f8fa9b78811..372d49d6e3d 100644
--- a/dlls/wined3d/adapter_vk.c
+++ b/dlls/wined3d/adapter_vk.c
@@ -23,6 +23,7 @@
#include "wine/vulkan_driver.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
static const struct wined3d_state_entry_template misc_state_template_vk[] =
{
@@ -1216,6 +1217,53 @@ static void adapter_vk_flush_bo_address(struct wined3d_context *context,
flush_bo_range(context_vk, bo, (uintptr_t)data->addr, size);
}
+struct wined3d_client_bo_vk_map_ctx
+{
+ struct wined3d_device *device;
+ struct wined3d_client_bo_vk *client_bo;
+};
+
+static bool adapter_vk_alloc_bo(struct wined3d_device *device, struct wined3d_resource *resource,
+ unsigned int sub_resource_idx, struct wined3d_bo_address *addr)
+{
+ struct wined3d_device_vk *device_vk = wined3d_device_vk(device);
+ struct wined3d_context_vk *context_vk = &device_vk->context_vk;
+
+ wined3d_not_from_cs(device->cs);
+ assert(device->context_count);
+
+ if (resource->type == WINED3D_RTYPE_BUFFER)
+ {
+ struct wined3d_client_bo_vk *client_bo;
+
+ if (!(client_bo = heap_alloc(sizeof(*client_bo))))
+ return false;
+
+ if (!(wined3d_context_vk_create_bo(context_vk, resource->size,
+ vk_buffer_usage_from_bind_flags(resource->bind_flags),
+ vk_memory_type_from_access_flags(resource->access, resource->usage), &client_bo->bo)))
+ {
+ WARN("Failed to create Vulkan buffer.\n");
+ return FALSE;
+ }
+
+ if (!client_bo->bo.b.map_ptr)
+ {
+ WARN_(d3d_perf)("BO %p (chunk %p, slab %p) is not persistently mapped.\n", &client_bo->bo,
+ client_bo->bo.memory ? client_bo->bo.memory->chunk : NULL, client_bo->bo.slab);
+
+ if (!wined3d_bo_vk_map(&client_bo->bo, context_vk))
+ ERR("Failed to map bo.\n");
+ }
+
+ addr->buffer_object = (uintptr_t)&client_bo->bo;
+ addr->addr = NULL;
+ return true;
+ }
+
+ return false;
+}
+
static HRESULT adapter_vk_create_swapchain(struct wined3d_device *device,
struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent,
void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain)
@@ -1868,6 +1916,7 @@ static const struct wined3d_adapter_ops wined3d_adapter_vk_ops =
.adapter_unmap_bo_address = adapter_vk_unmap_bo_address,
.adapter_copy_bo_address = adapter_vk_copy_bo_address,
.adapter_flush_bo_address = adapter_vk_flush_bo_address,
+ .adapter_alloc_bo = adapter_vk_alloc_bo,
.adapter_create_swapchain = adapter_vk_create_swapchain,
.adapter_destroy_swapchain = adapter_vk_destroy_swapchain,
.adapter_create_buffer = adapter_vk_create_buffer,
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index 0a72f19935b..d0ec4d5aef3 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -1061,6 +1061,16 @@ static HRESULT buffer_resource_sub_resource_unmap(struct wined3d_resource *resou
return WINED3D_OK;
}
+void wined3d_buffer_set_bo(struct wined3d_buffer *buffer, struct wined3d_context *context, struct wined3d_bo *bo)
+{
+ TRACE("buffer %p, context %p, bo %p.\n", buffer, context, bo);
+
+ buffer->buffer_ops->buffer_set_bo(buffer, context, bo);
+ buffer->buffer_object = (uintptr_t)bo;
+ wined3d_buffer_validate_location(buffer, WINED3D_LOCATION_BUFFER);
+ wined3d_buffer_invalidate_location(buffer, ~WINED3D_LOCATION_BUFFER);
+}
+
void wined3d_buffer_copy_bo_address(struct wined3d_buffer *dst_buffer, struct wined3d_context *context,
unsigned int dst_offset, const struct wined3d_const_bo_address *src_addr, unsigned int size)
{
@@ -1256,12 +1266,19 @@ static void wined3d_buffer_no3d_download_ranges(struct wined3d_buffer *buffer, s
FIXME("Not implemented.\n");
}
+static void wined3d_buffer_no3d_set_bo(struct wined3d_buffer *buffer,
+ struct wined3d_context *context, struct wined3d_bo *bo)
+{
+ FIXME("Not implemented.\n");
+}
+
static const struct wined3d_buffer_ops wined3d_buffer_no3d_ops =
{
wined3d_buffer_no3d_prepare_location,
wined3d_buffer_no3d_unload_location,
wined3d_buffer_no3d_upload_ranges,
wined3d_buffer_no3d_download_ranges,
+ wined3d_buffer_no3d_set_bo,
};
HRESULT wined3d_buffer_no3d_init(struct wined3d_buffer *buffer_no3d, struct wined3d_device *device,
@@ -1366,12 +1383,19 @@ static void wined3d_buffer_gl_download_ranges(struct wined3d_buffer *buffer, str
checkGLcall("buffer download");
}
+static void wined3d_buffer_gl_set_bo(struct wined3d_buffer *buffer,
+ struct wined3d_context *context, struct wined3d_bo *bo)
+{
+ FIXME("Not implemented.\n");
+}
+
static const struct wined3d_buffer_ops wined3d_buffer_gl_ops =
{
wined3d_buffer_gl_prepare_location,
wined3d_buffer_gl_unload_location,
wined3d_buffer_gl_upload_ranges,
wined3d_buffer_gl_download_ranges,
+ wined3d_buffer_gl_set_bo,
};
HRESULT wined3d_buffer_gl_init(struct wined3d_buffer_gl *buffer_gl, struct wined3d_device *device,
@@ -1399,7 +1423,7 @@ HRESULT wined3d_buffer_gl_init(struct wined3d_buffer_gl *buffer_gl, struct wined
return wined3d_buffer_init(&buffer_gl->b, device, desc, data, parent, parent_ops, &wined3d_buffer_gl_ops);
}
-static VkBufferUsageFlags vk_buffer_usage_from_bind_flags(uint32_t bind_flags)
+VkBufferUsageFlags vk_buffer_usage_from_bind_flags(uint32_t bind_flags)
{
VkBufferUsageFlags usage;
@@ -1423,7 +1447,7 @@ static VkBufferUsageFlags vk_buffer_usage_from_bind_flags(uint32_t bind_flags)
return usage;
}
-static VkMemoryPropertyFlags vk_memory_type_from_access_flags(uint32_t access, uint32_t usage)
+VkMemoryPropertyFlags vk_memory_type_from_access_flags(uint32_t access, uint32_t usage)
{
VkMemoryPropertyFlags memory_type = 0;
@@ -1577,12 +1601,49 @@ static void wined3d_buffer_vk_download_ranges(struct wined3d_buffer *buffer, str
FIXME("Not implemented.\n");
}
+static void wined3d_buffer_vk_set_bo(struct wined3d_buffer *buffer,
+ struct wined3d_context *context, struct wined3d_bo *bo)
+{
+ struct wined3d_bo_vk *prev_bo = (struct wined3d_bo_vk *)buffer->buffer_object;
+ struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
+ struct wined3d_buffer_vk *buffer_vk = wined3d_buffer_vk(buffer);
+ struct wined3d_bo_vk *bo_vk = wined3d_bo_vk(bo);
+
+ /* We can't just copy the contents of bo_vk into buffer_vk->bo, because the
+ * new BO might still be in use by the client thread. We could allow both to
+ * be valid, although knowing when to destroy a BO then becomes tricky, and
+ * ensuring it's not mapped more than once also becomes tricky. */
+
+ if (prev_bo)
+ {
+ struct wined3d_bo_user *bo_user;
+
+ LIST_FOR_EACH_ENTRY(bo_user, &prev_bo->b.users, struct wined3d_bo_user, entry)
+ bo_user->valid = false;
+ assert(list_empty(&bo_vk->b.users));
+ list_move_head(&bo_vk->b.users, &prev_bo->b.users);
+
+ if (prev_bo != &buffer_vk->bo)
+ {
+ struct wined3d_client_bo_vk *client_bo = CONTAINING_RECORD(prev_bo, struct wined3d_client_bo_vk, bo);
+
+ wined3d_context_vk_destroy_bo(context_vk, &client_bo->bo);
+ heap_free(client_bo);
+ }
+ }
+ else
+ {
+ list_add_head(&bo_vk->b.users, &buffer_vk->b.bo_user.entry);
+ }
+}
+
static const struct wined3d_buffer_ops wined3d_buffer_vk_ops =
{
wined3d_buffer_vk_prepare_location,
wined3d_buffer_vk_unload_location,
wined3d_buffer_vk_upload_ranges,
wined3d_buffer_vk_download_ranges,
+ wined3d_buffer_vk_set_bo,
};
HRESULT wined3d_buffer_vk_init(struct wined3d_buffer_vk *buffer_vk, struct wined3d_device *device,
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index e6ff448b028..fbbfce006ff 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -2747,6 +2747,9 @@ static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const voi
struct wined3d_buffer *buffer = buffer_from_resource(resource);
size_t size = box->right - box->left;
+ if (op->bo.flags & UPLOAD_BO_RENAME_ON_UNMAP)
+ wined3d_buffer_set_bo(buffer, context, (struct wined3d_bo *)op->bo.addr.buffer_object);
+
if (op->bo.addr.buffer_object && op->bo.addr.buffer_object == buffer->buffer_object)
wined3d_context_flush_bo_address(context, &op->bo.addr, size);
else
@@ -3121,12 +3124,20 @@ static bool wined3d_cs_map_upload_bo(struct wined3d_device_context *context, str
{
/* Limit NOOVERWRITE maps to buffers for now; there are too many ways that
* a texture can be invalidated to even count. */
- if (wined3d_map_persistent() && resource->type == WINED3D_RTYPE_BUFFER && (flags & WINED3D_MAP_NOOVERWRITE))
+ if (wined3d_map_persistent() && resource->type == WINED3D_RTYPE_BUFFER
+ && (flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE)))
{
struct wined3d_client_resource *client = &resource->client;
+ struct wined3d_device *device = context->device;
const struct wined3d_bo *bo;
uint8_t *map_ptr;
+ if (flags & WINED3D_MAP_DISCARD)
+ {
+ if (!device->adapter->adapter_ops->adapter_alloc_bo(device, resource, sub_resource_idx, &client->addr))
+ return NULL;
+ }
+
bo = (const struct wined3d_bo *)client->addr.buffer_object;
map_ptr = bo ? bo->map_ptr : NULL;
map_ptr += (uintptr_t)client->addr.addr;
@@ -3150,6 +3161,9 @@ static bool wined3d_cs_map_upload_bo(struct wined3d_device_context *context, str
}
map_desc->data = resource_offset_map_pointer(resource, sub_resource_idx, map_ptr, box);
+ if (flags & WINED3D_MAP_DISCARD)
+ client->mapped_upload.flags |= UPLOAD_BO_UPLOAD_ON_UNMAP | UPLOAD_BO_RENAME_ON_UNMAP;
+
client->mapped_box = *box;
TRACE("Returning bo %s, flags %#x.\n", debug_const_bo_address(&client->mapped_upload.addr),
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index c265bdc8c95..f14f57fd3f4 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -2805,6 +2805,12 @@ static void adapter_no3d_flush_bo_address(struct wined3d_context *context,
{
}
+static bool adapter_no3d_alloc_bo(struct wined3d_device *device, struct wined3d_resource *resource,
+ unsigned int sub_resource_idx, struct wined3d_bo_address *addr)
+{
+ return false;
+}
+
static HRESULT adapter_no3d_create_swapchain(struct wined3d_device *device,
struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent,
void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain)
@@ -3075,6 +3081,7 @@ static const struct wined3d_adapter_ops wined3d_adapter_no3d_ops =
.adapter_unmap_bo_address = adapter_no3d_unmap_bo_address,
.adapter_copy_bo_address = adapter_no3d_copy_bo_address,
.adapter_flush_bo_address = adapter_no3d_flush_bo_address,
+ .adapter_alloc_bo = adapter_no3d_alloc_bo,
.adapter_create_swapchain = adapter_no3d_create_swapchain,
.adapter_destroy_swapchain = adapter_no3d_destroy_swapchain,
.adapter_create_buffer = adapter_no3d_create_buffer,
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index d8f680f50f4..1c25876719c 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -328,6 +328,8 @@ VkPipelineStageFlags vk_pipeline_stage_mask_from_bind_flags(uint32_t bind_flags)
VkShaderStageFlagBits vk_shader_stage_from_wined3d(enum wined3d_shader_type shader_type) DECLSPEC_HIDDEN;
VkAccessFlags vk_access_mask_from_buffer_usage(VkBufferUsageFlags usage) DECLSPEC_HIDDEN;
VkPipelineStageFlags vk_pipeline_stage_mask_from_buffer_usage(VkBufferUsageFlags usage) DECLSPEC_HIDDEN;
+VkBufferUsageFlags vk_buffer_usage_from_bind_flags(uint32_t bind_flags) DECLSPEC_HIDDEN;
+VkMemoryPropertyFlags vk_memory_type_from_access_flags(uint32_t access, uint32_t usage) DECLSPEC_HIDDEN;
static inline enum wined3d_cmp_func wined3d_sanitize_cmp_func(enum wined3d_cmp_func func)
{
@@ -1639,6 +1641,16 @@ struct wined3d_bo_vk
bool host_synced;
};
+static inline struct wined3d_bo_vk *wined3d_bo_vk(struct wined3d_bo *bo)
+{
+ return CONTAINING_RECORD(bo, struct wined3d_bo_vk, b);
+}
+
+struct wined3d_client_bo_vk
+{
+ struct wined3d_bo_vk bo;
+};
+
struct wined3d_bo_slab_vk_key
{
VkMemoryPropertyFlags memory_type;
@@ -3338,6 +3350,7 @@ bool wined3d_driver_info_init(struct wined3d_driver_info *driver_info,
UINT64 vram_bytes, UINT64 sysmem_bytes) DECLSPEC_HIDDEN;
#define UPLOAD_BO_UPLOAD_ON_UNMAP 0x1
+#define UPLOAD_BO_RENAME_ON_UNMAP 0x2
struct upload_bo
{
@@ -3370,6 +3383,8 @@ struct wined3d_adapter_ops
const struct wined3d_bo_address *dst, const struct wined3d_bo_address *src, size_t size);
void (*adapter_flush_bo_address)(struct wined3d_context *context,
const struct wined3d_const_bo_address *data, size_t size);
+ bool (*adapter_alloc_bo)(struct wined3d_device *device, struct wined3d_resource *resource,
+ unsigned int sub_resource_idx, struct wined3d_bo_address *addr);
HRESULT (*adapter_create_swapchain)(struct wined3d_device *device,
struct wined3d_swapchain_desc *desc,
struct wined3d_swapchain_state_parent *state_parent, void *parent,
@@ -5016,6 +5031,7 @@ struct wined3d_buffer_ops
unsigned int data_offset, unsigned int range_count, const struct wined3d_range *ranges);
void (*buffer_download_ranges)(struct wined3d_buffer *buffer, struct wined3d_context *context, void *data,
unsigned int data_offset, unsigned int range_count, const struct wined3d_range *ranges);
+ void (*buffer_set_bo)(struct wined3d_buffer *buffer, struct wined3d_context *context, struct wined3d_bo *bo);
};
struct wined3d_buffer
@@ -5061,6 +5077,8 @@ BOOL wined3d_buffer_load_location(struct wined3d_buffer *buffer,
BYTE *wined3d_buffer_load_sysmem(struct wined3d_buffer *buffer, struct wined3d_context *context) DECLSPEC_HIDDEN;
BOOL wined3d_buffer_prepare_location(struct wined3d_buffer *buffer,
struct wined3d_context *context, unsigned int location) DECLSPEC_HIDDEN;
+void wined3d_buffer_set_bo(struct wined3d_buffer *buffer,
+ struct wined3d_context *context, struct wined3d_bo *bo) DECLSPEC_HIDDEN;
HRESULT wined3d_buffer_no3d_init(struct wined3d_buffer *buffer_no3d, struct wined3d_device *device,
const struct wined3d_buffer_desc *desc, const struct wined3d_sub_resource_data *data,
--
2.33.0
Nov. 4, 2021
[PATCH v2 6/7] wined3d: Protect wined3d_bo_slab_vk map fields with a mutex.
by Zebediah Figura
So as to allow slabs to be mapped from the client thread.
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/wined3d/adapter_vk.c | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c
index 8413429bd42..f8fa9b78811 100644
--- a/dlls/wined3d/adapter_vk.c
+++ b/dlls/wined3d/adapter_vk.c
@@ -845,28 +845,53 @@ static void wined3d_bo_vk_unmap(struct wined3d_bo_vk *bo, struct wined3d_context
VK_CALL(vkUnmapMemory(device_vk->vk_device, bo->vk_memory));
}
+static void wined3d_bo_slab_vk_lock(struct wined3d_bo_slab_vk *slab_vk, struct wined3d_context_vk *context_vk)
+{
+ wined3d_device_vk_allocator_lock(wined3d_device_vk(context_vk->c.device));
+}
+
+static void wined3d_bo_slab_vk_unlock(struct wined3d_bo_slab_vk *slab_vk, struct wined3d_context_vk *context_vk)
+{
+ wined3d_device_vk_allocator_unlock(wined3d_device_vk(context_vk->c.device));
+}
+
void *wined3d_bo_slab_vk_map(struct wined3d_bo_slab_vk *slab_vk, struct wined3d_context_vk *context_vk)
{
+ void *map_ptr;
+
TRACE("slab_vk %p, context_vk %p.\n", slab_vk, context_vk);
+ wined3d_bo_slab_vk_lock(slab_vk, context_vk);
+
if (!slab_vk->map_ptr && !(slab_vk->map_ptr = wined3d_bo_vk_map(&slab_vk->bo, context_vk)))
{
+ wined3d_bo_slab_vk_unlock(slab_vk, context_vk);
ERR("Failed to map slab.\n");
return NULL;
}
++slab_vk->map_count;
+ map_ptr = slab_vk->map_ptr;
- return slab_vk->map_ptr;
+ wined3d_bo_slab_vk_unlock(slab_vk, context_vk);
+
+ return map_ptr;
}
void wined3d_bo_slab_vk_unmap(struct wined3d_bo_slab_vk *slab_vk, struct wined3d_context_vk *context_vk)
{
+ wined3d_bo_slab_vk_lock(slab_vk, context_vk);
+
if (--slab_vk->map_count)
+ {
+ wined3d_bo_slab_vk_unlock(slab_vk, context_vk);
return;
+ }
wined3d_bo_vk_unmap(&slab_vk->bo, context_vk);
slab_vk->map_ptr = NULL;
+
+ wined3d_bo_slab_vk_unlock(slab_vk, context_vk);
}
VkAccessFlags vk_access_mask_from_buffer_usage(VkBufferUsageFlags usage)
--
2.33.0
Nov. 4, 2021
[PATCH v2 5/7] wined3d: Protect wined3d_chunk_vk map fields with a mutex.
by Zebediah Figura
So as to allow chunks to be mapped from the client thread.
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/wined3d/adapter_vk.c | 2 +-
dlls/wined3d/context_vk.c | 27 +++++++++++++++++++++++++--
dlls/wined3d/wined3d_private.h | 5 +++++
3 files changed, 31 insertions(+), 3 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c
index 5c83db9bfc9..8413429bd42 100644
--- a/dlls/wined3d/adapter_vk.c
+++ b/dlls/wined3d/adapter_vk.c
@@ -380,7 +380,7 @@ static void wined3d_allocator_vk_destroy_chunk(struct wined3d_allocator_chunk *c
TRACE("chunk %p.\n", chunk);
- device_vk = CONTAINING_RECORD(chunk_vk->c.allocator, struct wined3d_device_vk, allocator);
+ device_vk = wined3d_device_vk_from_allocator(chunk_vk->c.allocator);
vk_info = &device_vk->vk_info;
if (chunk_vk->c.map_ptr)
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c
index 854a800c0e4..619f722f809 100644
--- a/dlls/wined3d/context_vk.c
+++ b/dlls/wined3d/context_vk.c
@@ -247,26 +247,42 @@ static VkStencilOp vk_stencil_op_from_wined3d(enum wined3d_stencil_op op)
}
}
+static void wined3d_allocator_chunk_vk_lock(struct wined3d_allocator_chunk_vk *chunk_vk)
+{
+ wined3d_device_vk_allocator_lock(wined3d_device_vk_from_allocator(chunk_vk->c.allocator));
+}
+
+static void wined3d_allocator_chunk_vk_unlock(struct wined3d_allocator_chunk_vk *chunk_vk)
+{
+ wined3d_device_vk_allocator_unlock(wined3d_device_vk_from_allocator(chunk_vk->c.allocator));
+}
+
void *wined3d_allocator_chunk_vk_map(struct wined3d_allocator_chunk_vk *chunk_vk,
struct wined3d_context_vk *context_vk)
{
struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
const struct wined3d_vk_info *vk_info = context_vk->vk_info;
+ void *map_ptr;
VkResult vr;
TRACE("chunk %p, memory 0x%s, map_ptr %p.\n", chunk_vk,
wine_dbgstr_longlong(chunk_vk->vk_memory), chunk_vk->c.map_ptr);
+ wined3d_allocator_chunk_vk_lock(chunk_vk);
+
if (!chunk_vk->c.map_ptr && (vr = VK_CALL(vkMapMemory(device_vk->vk_device,
- chunk_vk->vk_memory, 0, VK_WHOLE_SIZE, 0, &chunk_vk->c.map_ptr))) < 0)
+ chunk_vk->vk_memory, 0, VK_WHOLE_SIZE, 0, &map_ptr))) < 0)
{
ERR("Failed to map chunk memory, vr %s.\n", wined3d_debug_vkresult(vr));
return NULL;
}
+ chunk_vk->c.map_ptr = map_ptr;
++chunk_vk->c.map_count;
- return chunk_vk->c.map_ptr;
+ wined3d_allocator_chunk_vk_unlock(chunk_vk);
+
+ return map_ptr;
}
void wined3d_allocator_chunk_vk_unmap(struct wined3d_allocator_chunk_vk *chunk_vk,
@@ -277,11 +293,18 @@ void wined3d_allocator_chunk_vk_unmap(struct wined3d_allocator_chunk_vk *chunk_v
TRACE("chunk_vk %p, context_vk %p.\n", chunk_vk, context_vk);
+ wined3d_allocator_chunk_vk_lock(chunk_vk);
+
if (--chunk_vk->c.map_count)
+ {
+ wined3d_allocator_chunk_vk_unlock(chunk_vk);
return;
+ }
VK_CALL(vkUnmapMemory(device_vk->vk_device, chunk_vk->vk_memory));
chunk_vk->c.map_ptr = NULL;
+
+ wined3d_allocator_chunk_vk_unlock(chunk_vk);
}
VkDeviceMemory wined3d_context_vk_allocate_vram_chunk_memory(struct wined3d_context_vk *context_vk,
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index f1f03abc2b5..d8f680f50f4 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -4095,6 +4095,11 @@ static inline struct wined3d_device_vk *wined3d_device_vk(struct wined3d_device
return CONTAINING_RECORD(device, struct wined3d_device_vk, d);
}
+static inline struct wined3d_device_vk *wined3d_device_vk_from_allocator(struct wined3d_allocator *allocator)
+{
+ return CONTAINING_RECORD(allocator, struct wined3d_device_vk, allocator);
+}
+
static inline void wined3d_device_vk_allocator_lock(struct wined3d_device_vk *device_vk)
{
EnterCriticalSection(&device_vk->allocator_cs);
--
2.33.0
Nov. 4, 2021
[PATCH v2 4/7] wined3d: Avoid accessing the "bo" member of struct wined3d_buffer_vk.
by Zebediah Figura
So as to allow the "buffer_object" field to point to other another
wined3d_bo_vk; namely, one allocated and still in use by the client thread.
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/wined3d/adapter_vk.c | 4 ++--
dlls/wined3d/buffer.c | 13 ++++++++-----
dlls/wined3d/context_vk.c | 8 ++++----
dlls/wined3d/view.c | 14 ++++++++++----
dlls/wined3d/wined3d_private.h | 2 +-
5 files changed, 25 insertions(+), 16 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c
index cbf7c94fd3a..5c83db9bfc9 100644
--- a/dlls/wined3d/adapter_vk.c
+++ b/dlls/wined3d/adapter_vk.c
@@ -1720,7 +1720,7 @@ static void adapter_vk_draw_primitive(struct wined3d_device *device,
if (parameters->indirect)
{
- struct wined3d_bo_vk *bo = &indirect_vk->bo;
+ struct wined3d_bo_vk *bo = (struct wined3d_bo_vk *)indirect_vk->b.buffer_object;
uint32_t stride, size;
wined3d_context_vk_reference_bo(context_vk, bo);
@@ -1792,7 +1792,7 @@ static void adapter_vk_dispatch_compute(struct wined3d_device *device,
if (parameters->indirect)
{
- struct wined3d_bo_vk *bo = &indirect_vk->bo;
+ struct wined3d_bo_vk *bo = (struct wined3d_bo_vk *)indirect_vk->b.buffer_object;
wined3d_context_vk_reference_bo(context_vk, bo);
VK_CALL(vkCmdDispatchIndirect(vk_command_buffer, bo->vk_buffer,
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index 62f84c96f96..0a72f19935b 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -1459,11 +1459,13 @@ static BOOL wined3d_buffer_vk_create_buffer_object(struct wined3d_buffer_vk *buf
const VkDescriptorBufferInfo *wined3d_buffer_vk_get_buffer_info(struct wined3d_buffer_vk *buffer_vk)
{
+ struct wined3d_bo_vk *bo = (struct wined3d_bo_vk *)buffer_vk->b.buffer_object;
+
if (buffer_vk->b.bo_user.valid)
return &buffer_vk->buffer_info;
- buffer_vk->buffer_info.buffer = buffer_vk->bo.vk_buffer;
- buffer_vk->buffer_info.offset = buffer_vk->bo.buffer_offset;
+ buffer_vk->buffer_info.buffer = bo->vk_buffer;
+ buffer_vk->buffer_info.offset = bo->buffer_offset;
buffer_vk->buffer_info.range = buffer_vk->b.resource.size;
buffer_vk->b.bo_user.valid = true;
@@ -1537,7 +1539,7 @@ static void wined3d_buffer_vk_upload_ranges(struct wined3d_buffer *buffer, struc
if (!ranges->offset && ranges->size == resource->size)
flags |= WINED3D_MAP_DISCARD;
- dst_bo = &wined3d_buffer_vk(buffer)->bo;
+ dst_bo = (struct wined3d_bo_vk *)buffer->buffer_object;
if (!(dst_bo->memory_type & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) || (!(flags & WINED3D_MAP_DISCARD)
&& dst_bo->command_buffer_id > context_vk->completed_command_buffer_id))
{
@@ -1629,6 +1631,7 @@ void wined3d_buffer_vk_barrier(struct wined3d_buffer_vk *buffer_vk,
if (src_bind_mask)
{
+ const struct wined3d_bo_vk *bo = (struct wined3d_bo_vk *)buffer_vk->b.buffer_object;
const struct wined3d_vk_info *vk_info = context_vk->vk_info;
VkBufferMemoryBarrier vk_barrier;
@@ -1643,8 +1646,8 @@ void wined3d_buffer_vk_barrier(struct wined3d_buffer_vk *buffer_vk,
vk_barrier.dstAccessMask = vk_access_mask_from_bind_flags(bind_mask);
vk_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
vk_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- vk_barrier.buffer = buffer_vk->bo.vk_buffer;
- vk_barrier.offset = buffer_vk->bo.buffer_offset;
+ vk_barrier.buffer = bo->vk_buffer;
+ vk_barrier.offset = bo->buffer_offset;
vk_barrier.size = buffer_vk->b.resource.size;
VK_CALL(vkCmdPipelineBarrier(wined3d_context_vk_get_command_buffer(context_vk),
vk_pipeline_stage_mask_from_bind_flags(src_bind_mask),
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c
index 54c5eb6bc24..854a800c0e4 100644
--- a/dlls/wined3d/context_vk.c
+++ b/dlls/wined3d/context_vk.c
@@ -2496,7 +2496,7 @@ static void wined3d_context_vk_bind_vertex_buffers(struct wined3d_context_vk *co
{
buffer_vk = wined3d_buffer_vk(buffer);
buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
- wined3d_context_vk_reference_bo(context_vk, &buffer_vk->bo);
+ wined3d_context_vk_reference_bo(context_vk, (struct wined3d_bo_vk *)buffer->buffer_object);
buffers[count] = buffer_info->buffer;
offsets[count] = buffer_info->offset + stream->offset;
++count;
@@ -2535,7 +2535,7 @@ static void wined3d_context_vk_bind_stream_output_buffers(struct wined3d_context
{
buffer_vk = wined3d_buffer_vk(buffer);
buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
- wined3d_context_vk_reference_bo(context_vk, &buffer_vk->bo);
+ wined3d_context_vk_reference_bo(context_vk, (struct wined3d_bo_vk *)buffer->buffer_object);
buffers[count] = buffer_info->buffer;
if ((offsets[count] = stream->offset) == ~0u)
{
@@ -2737,7 +2737,7 @@ static bool wined3d_shader_descriptor_writes_vk_add_cbv_write(struct wined3d_sha
if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
binding->binding_idx, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, buffer_info, NULL, NULL))
return false;
- wined3d_context_vk_reference_bo(context_vk, &buffer_vk->bo);
+ wined3d_context_vk_reference_bo(context_vk, (struct wined3d_bo_vk *)buffer->buffer_object);
return true;
}
@@ -3385,7 +3385,7 @@ VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *c
idx_type = VK_INDEX_TYPE_UINT32;
buffer_vk = wined3d_buffer_vk(state->index_buffer);
buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
- wined3d_context_vk_reference_bo(context_vk, &buffer_vk->bo);
+ wined3d_context_vk_reference_bo(context_vk, (struct wined3d_bo_vk *)buffer_vk->b.buffer_object);
VK_CALL(vkCmdBindIndexBuffer(vk_command_buffer, buffer_info->buffer,
buffer_info->offset + state->index_offset, idx_type));
}
diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c
index 374e693b17d..ee398be15f0 100644
--- a/dlls/wined3d/view.c
+++ b/dlls/wined3d/view.c
@@ -672,17 +672,19 @@ static VkBufferView wined3d_view_vk_create_vk_buffer_view(struct wined3d_context
struct wined3d_device_vk *device_vk;
VkBufferView vk_buffer_view;
unsigned int offset, size;
+ struct wined3d_bo_vk *bo;
VkResult vr;
get_buffer_view_range(&buffer_vk->b, desc, &view_format_vk->f, &offset, &size);
wined3d_buffer_prepare_location(&buffer_vk->b, &context_vk->c, WINED3D_LOCATION_BUFFER);
+ bo = (struct wined3d_bo_vk *)buffer_vk->b.buffer_object;
create_info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
create_info.pNext = NULL;
create_info.flags = 0;
- create_info.buffer = buffer_vk->bo.vk_buffer;
+ create_info.buffer = bo->vk_buffer;
create_info.format = view_format_vk->vk_format;
- create_info.offset = buffer_vk->bo.buffer_offset + offset;
+ create_info.offset = bo->buffer_offset + offset;
create_info.range = size;
device_vk = wined3d_device_vk(buffer_vk->b.resource.device);
@@ -1082,6 +1084,7 @@ static void wined3d_shader_resource_view_vk_cs_init(void *object)
VkBufferView vk_buffer_view;
uint32_t default_flags = 0;
VkImageView vk_image_view;
+ struct wined3d_bo_vk *bo;
TRACE("srv_vk %p.\n", srv_vk);
@@ -1099,12 +1102,13 @@ static void wined3d_shader_resource_view_vk_cs_init(void *object)
if (!vk_buffer_view)
return;
+ bo = (struct wined3d_bo_vk *)buffer_vk->b.buffer_object;
TRACE("Created buffer view 0x%s.\n", wine_dbgstr_longlong(vk_buffer_view));
srv_vk->view_vk.u.vk_buffer_view = vk_buffer_view;
srv_vk->view_vk.bo_user.valid = true;
- list_add_head(&buffer_vk->bo.b.users, &srv_vk->view_vk.bo_user.entry);
+ list_add_head(&bo->b.users, &srv_vk->view_vk.bo_user.entry);
return;
}
@@ -2204,11 +2208,13 @@ static void wined3d_unordered_access_view_vk_cs_init(void *object)
if ((vk_buffer_view = wined3d_view_vk_create_vk_buffer_view(context_vk, desc, buffer_vk, format_vk)))
{
+ struct wined3d_bo_vk *bo = (struct wined3d_bo_vk *)buffer_vk->b.buffer_object;
+
TRACE("Created buffer view 0x%s.\n", wine_dbgstr_longlong(vk_buffer_view));
uav_vk->view_vk.u.vk_buffer_view = vk_buffer_view;
uav_vk->view_vk.bo_user.valid = true;
- list_add_head(&buffer_vk->bo.b.users, &view_vk->bo_user.entry);
+ list_add_head(&bo->b.users, &view_vk->bo_user.entry);
}
if (desc->flags & (WINED3D_VIEW_BUFFER_COUNTER | WINED3D_VIEW_BUFFER_APPEND))
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 62b92ce7c34..f1f03abc2b5 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -6298,7 +6298,7 @@ static inline void wined3d_context_vk_reference_resource(const struct wined3d_co
struct wined3d_resource *resource)
{
if (resource->type == WINED3D_RTYPE_BUFFER)
- wined3d_context_vk_reference_bo(context_vk, &wined3d_buffer_vk(buffer_from_resource(resource))->bo);
+ wined3d_context_vk_reference_bo(context_vk, (struct wined3d_bo_vk *)buffer_from_resource(resource)->buffer_object);
else
wined3d_context_vk_reference_texture(context_vk, wined3d_texture_vk(texture_from_resource(resource)));
}
--
2.33.0
Nov. 4, 2021