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 4/5] comctl32/button: Correctly place parts for themed group boxes.
by Zhiyi Zhang
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/comctl32/button.c | 49 +++++++++++++++++++++++-------------------
1 file changed, 27 insertions(+), 22 deletions(-)
diff --git a/dlls/comctl32/button.c b/dlls/comctl32/button.c
index 515dff03921..7b617a199b0 100644
--- a/dlls/comctl32/button.c
+++ b/dlls/comctl32/button.c
@@ -2855,11 +2855,12 @@ cleanup:
static void GB_ThemedPaint(HTHEME theme, const BUTTON_INFO *infoPtr, HDC hDC, int state, UINT dtFlags, BOOL focused)
{
- RECT bgRect, textRect, contentRect;
- WCHAR *text = get_button_text(infoPtr);
+ RECT clientRect, contentRect, imageRect, textRect, bgRect;
+ HRGN region, textRegion = NULL;
LOGFONTW lf;
HFONT font, hPrevFont = NULL;
BOOL created_font = FALSE;
+ TEXTMETRICW textMetric;
HRESULT hr = GetThemeFont(theme, hDC, BP_GROUPBOX, state, TMT_FONT, &lf);
if (SUCCEEDED(hr)) {
@@ -2875,37 +2876,41 @@ static void GB_ThemedPaint(HTHEME theme, const BUTTON_INFO *infoPtr, HDC hDC, in
SelectObject(hDC, infoPtr->font);
}
- GetClientRect(infoPtr->hwnd, &bgRect);
- textRect = bgRect;
+ GetClientRect(infoPtr->hwnd, &clientRect);
+ GetThemeBackgroundContentRect(theme, hDC, BP_GROUPBOX, state, &clientRect, &contentRect);
+ region = set_control_clipping(hDC, &clientRect);
- if (text)
+ bgRect = contentRect;
+ GetTextMetricsW(hDC, &textMetric);
+ bgRect.top += (textMetric.tmHeight / 2) - 1;
+
+ InflateRect(&contentRect, -7, 1);
+ dtFlags = BUTTON_CalcLayoutRects(infoPtr, hDC, &contentRect, &imageRect, &textRect);
+ if (dtFlags != (UINT)-1 && !show_image_only(infoPtr))
{
- SIZE textExtent;
- GetTextExtentPoint32W(hDC, text, lstrlenW(text), &textExtent);
- bgRect.top += (textExtent.cy / 2);
- textRect.left += 10;
- textRect.bottom = textRect.top + textExtent.cy;
- textRect.right = textRect.left + textExtent.cx + 4;
-
- ExcludeClipRect(hDC, textRect.left, textRect.top, textRect.right, textRect.bottom);
+ textRegion = CreateRectRgnIndirect(&textRect);
+ ExtSelectClipRgn(hDC, textRegion, RGN_DIFF);
}
- GetThemeBackgroundContentRect(theme, hDC, BP_GROUPBOX, state, &bgRect, &contentRect);
- ExcludeClipRect(hDC, contentRect.left, contentRect.top, contentRect.right, contentRect.bottom);
-
if (IsThemeBackgroundPartiallyTransparent(theme, BP_GROUPBOX, state))
DrawThemeParentBackground(infoPtr->hwnd, hDC, NULL);
DrawThemeBackground(theme, hDC, BP_GROUPBOX, state, &bgRect, NULL);
- SelectClipRgn(hDC, NULL);
-
- if (text)
+ if (dtFlags != (UINT)-1)
{
- InflateRect(&textRect, -2, 0);
- DrawThemeText(theme, hDC, BP_GROUPBOX, state, text, lstrlenW(text), 0, 0, &textRect);
- heap_free(text);
+ contentRect.left--;
+ contentRect.right++;
+ contentRect.bottom++;
+ if (textRegion)
+ {
+ SelectClipRgn(hDC, textRegion);
+ DeleteObject(textRegion);
+ }
+ BUTTON_DrawThemedLabel(infoPtr, hDC, dtFlags, &imageRect, &textRect, theme, BP_GROUPBOX, state);
}
+ SelectClipRgn(hDC, region);
+ if (region) DeleteObject(region);
if (created_font) DeleteObject(font);
if (hPrevFont) SelectObject(hDC, hPrevFont);
}
--
2.32.0
Nov. 5, 2021
[PATCH 3/5] comctl32/button: Correctly place parts for themed check boxes.
by Zhiyi Zhang
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/comctl32/button.c | 76 +++++++++++++++++++++++-------------------
1 file changed, 42 insertions(+), 34 deletions(-)
diff --git a/dlls/comctl32/button.c b/dlls/comctl32/button.c
index 80635feaafc..515dff03921 100644
--- a/dlls/comctl32/button.c
+++ b/dlls/comctl32/button.c
@@ -2748,18 +2748,20 @@ static void PB_ThemedPaint(HTHEME theme, const BUTTON_INFO *infoPtr, HDC hDC, in
static void CB_ThemedPaint(HTHEME theme, const BUTTON_INFO *infoPtr, HDC hDC, int state, UINT dtFlags, BOOL focused)
{
- SIZE sz;
- RECT bgRect, textRect;
+ RECT client_rect, content_rect, old_label_rect, label_rect, box_rect, image_rect, text_rect;
HFONT font, hPrevFont = NULL;
DWORD dwStyle = GetWindowLongW(infoPtr->hwnd, GWL_STYLE);
+ LONG ex_style = GetWindowLongW(infoPtr->hwnd, GWL_EXSTYLE);
UINT btn_type = get_button_type( dwStyle );
int part = (btn_type == BS_RADIOBUTTON) || (btn_type == BS_AUTORADIOBUTTON) ? BP_RADIOBUTTON : BP_CHECKBOX;
NMCUSTOMDRAW nmcd;
LRESULT cdrf;
LOGFONTW lf;
HWND parent;
- WCHAR *text;
BOOL created_font = FALSE;
+ int text_offset;
+ SIZE box_size;
+ HRGN region;
HRESULT hr = GetThemeFont(theme, hDC, part, state, TMT_FONT, &lf);
if (SUCCEEDED(hr)) {
@@ -2775,20 +2777,31 @@ static void CB_ThemedPaint(HTHEME theme, const BUTTON_INFO *infoPtr, HDC hDC, in
if (infoPtr->font) SelectObject(hDC, infoPtr->font);
}
- if (FAILED(GetThemePartSize(theme, hDC, part, state, NULL, TS_DRAW, &sz)))
- sz.cx = sz.cy = 13;
+ GetClientRect(infoPtr->hwnd, &client_rect);
+ GetThemeBackgroundContentRect(theme, hDC, part, state, &client_rect, &content_rect);
+ region = set_control_clipping(hDC, &client_rect);
- GetClientRect(infoPtr->hwnd, &bgRect);
- GetThemeBackgroundContentRect(theme, hDC, part, state, &bgRect, &textRect);
- init_custom_draw(&nmcd, infoPtr, hDC, &bgRect);
+ if (FAILED(GetThemePartSize(theme, hDC, part, state, NULL, TS_DRAW, &box_size)))
+ {
+ box_size.cx = 12 * GetDpiForWindow(infoPtr->hwnd) / 96 + 1;
+ box_size.cy = box_size.cx;
+ }
- if (dtFlags & DT_SINGLELINE) /* Center the checkbox / radio button to the text. */
- bgRect.top = bgRect.top + (textRect.bottom - textRect.top - sz.cy) / 2;
+ GetCharWidthW(hDC, '0', '0', &text_offset);
+ text_offset /= 2;
- /* adjust for the check/radio marker */
- bgRect.bottom = bgRect.top + sz.cy;
- bgRect.right = bgRect.left + sz.cx;
- textRect.left = bgRect.right + 6;
+ label_rect = content_rect;
+ if (dwStyle & BS_LEFTTEXT || ex_style & WS_EX_RIGHT)
+ label_rect.right -= box_size.cx + text_offset;
+ else
+ label_rect.left += box_size.cx + text_offset;
+
+ old_label_rect = label_rect;
+ dtFlags = BUTTON_CalcLayoutRects(infoPtr, hDC, &label_rect, &image_rect, &text_rect);
+ box_rect = get_box_rect(dwStyle, ex_style, &content_rect, &label_rect, dtFlags != (UINT)-1L,
+ box_size);
+
+ init_custom_draw(&nmcd, infoPtr, hDC, &client_rect);
parent = GetParent(infoPtr->hwnd);
if (!parent) parent = infoPtr->hwnd;
@@ -2798,7 +2811,6 @@ static void CB_ThemedPaint(HTHEME theme, const BUTTON_INFO *infoPtr, HDC hDC, in
if (cdrf & CDRF_SKIPDEFAULT) goto cleanup;
DrawThemeParentBackground(infoPtr->hwnd, hDC, NULL);
- DrawThemeBackground(theme, hDC, part, state, &bgRect, NULL);
if (cdrf & CDRF_NOTIFYPOSTERASE)
{
@@ -2811,36 +2823,32 @@ static void CB_ThemedPaint(HTHEME theme, const BUTTON_INFO *infoPtr, HDC hDC, in
cdrf = SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd);
if (cdrf & CDRF_SKIPDEFAULT) goto cleanup;
- text = get_button_text(infoPtr);
- if (!(cdrf & CDRF_DOERASE) && text)
- DrawThemeText(theme, hDC, part, state, text, lstrlenW(text), dtFlags, 0, &textRect);
+ /* Draw label */
+ if (!(cdrf & CDRF_DOERASE))
+ {
+ DrawThemeBackground(theme, hDC, part, state, &box_rect, NULL);
+ if (dtFlags != (UINT)-1L)
+ BUTTON_DrawThemedLabel(infoPtr, hDC, dtFlags, &image_rect, &text_rect, theme, part, state);
+ }
if (cdrf & CDRF_NOTIFYPOSTPAINT)
{
nmcd.dwDrawStage = CDDS_POSTPAINT;
SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd);
}
+ if ((cdrf & CDRF_SKIPPOSTPAINT) || dtFlags == (UINT)-1L) goto cleanup;
- if (text)
+ if (focused)
{
- if (!(cdrf & CDRF_SKIPPOSTPAINT) && focused)
- {
- RECT focusRect;
-
- focusRect = textRect;
-
- DrawTextW(hDC, text, lstrlenW(text), &focusRect, dtFlags | DT_CALCRECT);
-
- if (focusRect.right < textRect.right) focusRect.right++;
- focusRect.bottom = textRect.bottom;
-
- DrawFocusRect( hDC, &focusRect );
- }
-
- heap_free(text);
+ label_rect.left--;
+ label_rect.right++;
+ IntersectRect(&label_rect, &label_rect, &old_label_rect);
+ DrawFocusRect(hDC, &label_rect);
}
cleanup:
+ SelectClipRgn(hDC, region);
+ if (region) DeleteObject(region);
if (created_font) DeleteObject(font);
if (hPrevFont) SelectObject(hDC, hPrevFont);
}
--
2.32.0
Nov. 5, 2021
[PATCH 2/5] comctl32/button: Correctly place parts for themed push buttons.
by Zhiyi Zhang
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51916
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/comctl32/button.c | 47 +++++++++++++++++++++++++++++++++++-------
1 file changed, 40 insertions(+), 7 deletions(-)
diff --git a/dlls/comctl32/button.c b/dlls/comctl32/button.c
index 70ac6b1c2da..80635feaafc 100644
--- a/dlls/comctl32/button.c
+++ b/dlls/comctl32/button.c
@@ -1761,6 +1761,38 @@ static void BUTTON_DrawLabel(const BUTTON_INFO *infoPtr, HDC hdc, UINT dtFlags,
heap_free(text);
}
+static void BUTTON_DrawThemedLabel(const BUTTON_INFO *info, HDC hdc, UINT text_flags,
+ const RECT *image_rect, const RECT *text_rect, HTHEME theme,
+ int part, int state)
+{
+ HBRUSH brush = NULL;
+ UINT image_flags;
+ WCHAR *text;
+
+ if (show_image(info))
+ {
+ image_flags = IsWindowEnabled(info->hwnd) ? DSS_NORMAL : DSS_DISABLED;
+
+ if ((GetWindowLongW(info->hwnd, GWL_STYLE) & BS_PUSHLIKE)
+ && (info->state & BST_INDETERMINATE))
+ {
+ brush = GetSysColorBrush(COLOR_GRAYTEXT);
+ image_flags |= DSS_MONO;
+ }
+
+ BUTTON_DrawImage(info, hdc, brush, image_flags, image_rect);
+ }
+
+ if (show_image_only(info))
+ return;
+
+ if (!(text = get_button_text(info)))
+ return;
+
+ DrawThemeText(theme, hdc, part, state, text, lstrlenW(text), text_flags, 0, text_rect);
+ heap_free(text);
+}
+
/**********************************************************************
* Push Button Functions
*/
@@ -2661,17 +2693,16 @@ cleanup:
*/
static void PB_ThemedPaint(HTHEME theme, const BUTTON_INFO *infoPtr, HDC hDC, int state, UINT dtFlags, BOOL focused)
{
- RECT bgRect, textRect, focusRect;
+ RECT bgRect, labelRect, imageRect, textRect, focusRect;
NMCUSTOMDRAW nmcd;
LRESULT cdrf;
HWND parent;
- WCHAR *text;
if (infoPtr->font) SelectObject(hDC, infoPtr->font);
GetClientRect(infoPtr->hwnd, &bgRect);
- GetThemeBackgroundContentRect(theme, hDC, BP_PUSHBUTTON, state, &bgRect, &textRect);
- focusRect = textRect;
+ GetThemeBackgroundContentRect(theme, hDC, BP_PUSHBUTTON, state, &bgRect, &labelRect);
+ focusRect = labelRect;
init_custom_draw(&nmcd, infoPtr, hDC, &bgRect);
@@ -2697,10 +2728,12 @@ static void PB_ThemedPaint(HTHEME theme, const BUTTON_INFO *infoPtr, HDC hDC, in
cdrf = SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd);
if (cdrf & CDRF_SKIPDEFAULT) return;
- if (!(cdrf & CDRF_DOERASE) && (text = get_button_text(infoPtr)))
+ if (!(cdrf & CDRF_DOERASE))
{
- DrawThemeText(theme, hDC, BP_PUSHBUTTON, state, text, lstrlenW(text), dtFlags, 0, &textRect);
- heap_free(text);
+ dtFlags = BUTTON_CalcLayoutRects(infoPtr, hDC, &labelRect, &imageRect, &textRect);
+ if (dtFlags != (UINT)-1L)
+ BUTTON_DrawThemedLabel(infoPtr, hDC, dtFlags, &imageRect, &textRect, theme,
+ BP_PUSHBUTTON, state);
}
if (cdrf & CDRF_NOTIFYPOSTPAINT)
--
2.32.0
Nov. 5, 2021
[PATCH 1/5] comctl32/button: Correctly place parts for buttons with WS_EX_RIGHT.
by Zhiyi Zhang
WS_EX_RIGHT has the same effect as BS_RIGHT.
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/comctl32/button.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/dlls/comctl32/button.c b/dlls/comctl32/button.c
index 6a463cb3460..70ac6b1c2da 100644
--- a/dlls/comctl32/button.c
+++ b/dlls/comctl32/button.c
@@ -1547,17 +1547,15 @@ static BOOL CL_GetIdealSize(BUTTON_INFO *infoPtr, SIZE *size)
*/
static UINT BUTTON_CalcLayoutRects(const BUTTON_INFO *infoPtr, HDC hdc, RECT *labelRc, RECT *imageRc, RECT *textRc)
{
- LONG style = GetWindowLongW( infoPtr->hwnd, GWL_STYLE );
- LONG ex_style = GetWindowLongW( infoPtr->hwnd, GWL_EXSTYLE );
- LONG split_style = infoPtr->imagelist.himl ? BUTTON_ILStoBS(infoPtr->imagelist.uAlign) : style;
WCHAR *text = get_button_text(infoPtr);
SIZE imageSize = BUTTON_GetImageSize(infoPtr);
- UINT dtStyle = BUTTON_BStoDT(style, ex_style);
RECT labelRect, imageRect, imageRectWithMargin, textRect;
LONG imageMarginWidth, imageMarginHeight;
const RECT *textMargin = BUTTON_GetTextMargin(infoPtr);
+ LONG style, ex_style, split_style;
RECT emptyMargin = {0};
LONG maxTextWidth;
+ UINT dtStyle;
/* Calculate label rectangle according to label type */
if ((imageSize.cx == 0 && imageSize.cy == 0) && (text == NULL || text[0] == '\0'))
@@ -1569,6 +1567,14 @@ static UINT BUTTON_CalcLayoutRects(const BUTTON_INFO *infoPtr, HDC hdc, RECT *la
return (UINT)-1;
}
+ style = GetWindowLongW(infoPtr->hwnd, GWL_STYLE);
+ ex_style = GetWindowLongW(infoPtr->hwnd, GWL_EXSTYLE);
+ /* Add BS_RIGHT directly. When both WS_EX_RIGHT and BS_LEFT are present, it becomes BS_CENTER */
+ if (ex_style & WS_EX_RIGHT)
+ style |= BS_RIGHT;
+ split_style = infoPtr->imagelist.himl ? BUTTON_ILStoBS(infoPtr->imagelist.uAlign) : style;
+ dtStyle = BUTTON_BStoDT(style, ex_style);
+
SetRect(&imageRect, 0, 0, imageSize.cx, imageSize.cy);
imageRectWithMargin = imageRect;
if (infoPtr->imagelist.himl)
--
2.32.0
Nov. 5, 2021
[PATCH] msdasql: Implement IDBProperties GetProperties
by Alistair Leslie-Hughes
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/msdasql/msdasql_main.c | 76 ++++++++++++++++++++++++++++++++++-
dlls/msdasql/tests/provider.c | 57 +++++++++++++++++++++++++-
dlls/oledb32/tests/database.c | 4 +-
3 files changed, 130 insertions(+), 7 deletions(-)
diff --git a/dlls/msdasql/msdasql_main.c b/dlls/msdasql/msdasql_main.c
index b8d68287e6a..d14f7957978 100644
--- a/dlls/msdasql/msdasql_main.c
+++ b/dlls/msdasql/msdasql_main.c
@@ -193,6 +193,12 @@ static const struct dbproperty dbproperties[] =
{ L"General Timeout", DBPROP_INIT_GENERALTIMEOUT, DBPROPOPTIONS_OPTIONAL, VT_I4 },
};
+struct msdasql_prop
+{
+ VARTYPE id;
+ VARIANT value;
+};
+
struct msdasql
{
IUnknown MSDASQL_iface;
@@ -202,6 +208,7 @@ struct msdasql
IPersist IPersist_iface;
LONG ref;
+ struct msdasql_prop properties[14];
};
static inline struct msdasql *impl_from_IUnknown(IUnknown *iface)
@@ -324,10 +331,49 @@ static HRESULT WINAPI dbprops_GetProperties(IDBProperties *iface, ULONG cPropert
const DBPROPIDSET rgPropertyIDSets[], ULONG *pcPropertySets, DBPROPSET **prgPropertySets)
{
struct msdasql *provider = impl_from_IDBProperties(iface);
+ int i, j, k;
+ DBPROPSET *propset;
- FIXME("(%p)->(%d %p %p %p)\n", provider, cPropertyIDSets, rgPropertyIDSets, pcPropertySets, prgPropertySets);
+ TRACE("(%p)->(%d %p %p %p)\n", provider, cPropertyIDSets, rgPropertyIDSets, pcPropertySets, prgPropertySets);
- return E_NOTIMPL;
+ *pcPropertySets = 1;
+
+ if (cPropertyIDSets != 1)
+ {
+ FIXME("Currently only 1 property set supported.\n");
+ cPropertyIDSets = 1;
+ }
+
+ propset = CoTaskMemAlloc(cPropertyIDSets * sizeof(DBPROPSET));
+ propset->guidPropertySet = DBPROPSET_DBINIT;
+
+ for (i=0; i < cPropertyIDSets; i++)
+ {
+ TRACE("Property id %d (count %d, set %s)\n", i, rgPropertyIDSets[i].cPropertyIDs,
+ debugstr_guid(&rgPropertyIDSets[i].guidPropertySet));
+
+ propset->cProperties = rgPropertyIDSets[i].cPropertyIDs;
+ propset->rgProperties = CoTaskMemAlloc(propset->cProperties * sizeof(DBPROP));
+
+ for (j=0; j < propset->cProperties; j++)
+ {
+ propset->rgProperties[j].dwPropertyID = rgPropertyIDSets[i].rgPropertyIDs[j];
+
+ for(k = 0; k < ARRAY_SIZE(provider->properties); k++)
+ {
+ if (provider->properties[k].id == rgPropertyIDSets[i].rgPropertyIDs[j])
+ {
+ V_VT(&propset->rgProperties[j].vValue) = VT_EMPTY;
+ VariantCopy(&propset->rgProperties[j].vValue, &provider->properties[k].value);
+ break;
+ }
+ }
+ }
+ }
+
+ *prgPropertySets = propset;
+
+ return S_OK;
}
static HRESULT WINAPI dbprops_GetPropertyInfo(IDBProperties *iface, ULONG cPropertyIDSets,
@@ -531,6 +577,7 @@ static HRESULT create_msdasql_provider(REFIID riid, void **ppv)
{
struct msdasql *provider;
HRESULT hr;
+ int i;
provider = malloc(sizeof(struct msdasql));
if (!provider)
@@ -543,6 +590,31 @@ static HRESULT create_msdasql_provider(REFIID riid, void **ppv)
provider->IPersist_iface.lpVtbl = &persistVtbl;
provider->ref = 1;
+ for(i=0; i < ARRAY_SIZE(dbproperties); i++)
+ {
+ provider->properties[i].id = dbproperties[i].id;
+ VariantInit(&provider->properties[i].value);
+
+ /* Only the follow are initialized to a value */
+ switch(dbproperties[i].id)
+ {
+ case DBPROP_INIT_PROMPT:
+ V_VT(&provider->properties[i].value) = dbproperties[i].type;
+ V_I2(&provider->properties[i].value) = 4;
+ break;
+ case DBPROP_INIT_LCID:
+ V_VT(&provider->properties[i].value) = dbproperties[i].type;
+ V_I4(&provider->properties[i].value) = GetUserDefaultLCID();
+ break;
+ case DBPROP_INIT_OLEDBSERVICES:
+ V_VT(&provider->properties[i].value) = dbproperties[i].type;
+ V_I4(&provider->properties[i].value) = -1;
+ break;
+ default:
+ V_VT(&provider->properties[i].value) = VT_EMPTY;
+ }
+ }
+
hr = IUnknown_QueryInterface(&provider->MSDASQL_iface, riid, ppv);
IUnknown_Release(&provider->MSDASQL_iface);
return hr;
diff --git a/dlls/msdasql/tests/provider.c b/dlls/msdasql/tests/provider.c
index 6cf95e02a80..6ffe17e7028 100644
--- a/dlls/msdasql/tests/provider.c
+++ b/dlls/msdasql/tests/provider.c
@@ -75,6 +75,14 @@ static void test_Properties(void)
ULONG infocount;
DBPROPINFOSET *propinfoset;
WCHAR *desc;
+ DBPROPID properties[14] =
+ {
+ DBPROP_AUTH_PASSWORD, DBPROP_AUTH_PERSIST_SENSITIVE_AUTHINFO, DBPROP_AUTH_USERID,
+ DBPROP_INIT_DATASOURCE, DBPROP_INIT_HWND, DBPROP_INIT_LOCATION,
+ DBPROP_INIT_MODE, DBPROP_INIT_PROMPT, DBPROP_INIT_TIMEOUT,
+ DBPROP_INIT_PROVIDERSTRING, DBPROP_INIT_LCID, DBPROP_INIT_CATALOG,
+ DBPROP_INIT_OLEDBSERVICES, DBPROP_INIT_GENERALTIMEOUT
+ };
hr = CoCreateInstance( &CLSID_MSDASQL, NULL, CLSCTX_ALL, &IID_IDBProperties, (void **)&props);
ok(hr == S_OK, "Failed to create object 0x%08x\n", hr);
@@ -88,18 +96,30 @@ static void test_Properties(void)
ok(hr == S_OK, "got 0x%08x\n", hr);
if (hr == S_OK)
{
- ULONG i;
VARTYPE types[14] = { VT_BSTR, VT_BOOL, VT_BSTR, VT_BSTR, intptr_vartype, VT_BSTR, VT_I4, VT_I2 , VT_I4, VT_BSTR, VT_I4, VT_BSTR, VT_I4, VT_I4 };
+ ULONG i;
+ DBPROPIDSET propidlist;
+ ULONG propcnt;
+ DBPROPSET *propset;
ok(IsEqualGUID(&propinfoset->guidPropertySet, &DBPROPSET_DBINIT), "got %s\n", debugstr_guid(&propinfoset->guidPropertySet));
ok(propinfoset->cPropertyInfos == 14, "got %d\n", propinfoset->cPropertyInfos);
+ propidlist.guidPropertySet = DBPROPSET_DBINIT;
+ propidlist.cPropertyIDs = propinfoset->cPropertyInfos;
+ propidlist.rgPropertyIDs = CoTaskMemAlloc(propinfoset->cPropertyInfos * sizeof(DBPROP));
+
for (i = 0; i < propinfoset->cPropertyInfos; i++)
{
- trace("%d: pwszDescription: %s\n", i, debugstr_w(propinfoset->rgPropertyInfos[i].pwszDescription) );
ok(propinfoset->rgPropertyInfos[i].vtType == types[i], "got %d\n", propinfoset->rgPropertyInfos[i].vtType);
ok(propinfoset->rgPropertyInfos[i].dwFlags == (DBPROPFLAGS_DBINIT | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE),
"got %d\n", propinfoset->rgPropertyInfos[i].dwFlags);
+ ok(properties[i] == propinfoset->rgPropertyInfos[i].dwPropertyID, "%d, got %d\n", i,
+ propinfoset->rgPropertyInfos[i].dwPropertyID);
+ ok(propinfoset->rgPropertyInfos[i].vtType != VT_EMPTY, "%d, got %d\n", i,
+ propinfoset->rgPropertyInfos[i].vtType);
+
+ propidlist.rgPropertyIDs[i] = propinfoset->rgPropertyInfos[i].dwPropertyID;
}
for (i = 0; i < propinfoset->cPropertyInfos; i++)
@@ -107,6 +127,39 @@ static void test_Properties(void)
CoTaskMemFree(propinfoset->rgPropertyInfos);
CoTaskMemFree(propinfoset);
+
+ hr = IDBProperties_GetProperties(props, 1, &propidlist, &propcnt, &propset);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(propidlist.cPropertyIDs == 14, "got %d\n", propinfoset->cPropertyInfos);
+ ok(propset->cProperties == 14, "got %d\n", propinfoset->cPropertyInfos);
+
+ for (i = 0; i < propidlist.cPropertyIDs; i++)
+ {
+ VARTYPE vartype = VT_EMPTY;
+
+ ok(properties[i] == propidlist.rgPropertyIDs[i], "%d, got %d\n", i, propidlist.rgPropertyIDs[i]);
+
+ if(properties[i] == DBPROP_INIT_PROMPT)
+ {
+ ok(V_I2(&propset->rgProperties[i].vValue) == 4, "wrong value %s\n", debugstr_variant(&propset->rgProperties[i].vValue));
+ vartype = VT_I2;
+ }
+ else if(properties[i] == DBPROP_INIT_LCID)
+ {
+ ok(V_I4(&propset->rgProperties[i].vValue) == GetUserDefaultLCID(), "wrong value %s\n", debugstr_variant(&propset->rgProperties[i].vValue));
+ vartype = VT_I4;
+ }
+ else if(properties[i] == DBPROP_INIT_OLEDBSERVICES)
+ {
+ ok(V_I4(&propset->rgProperties[i].vValue) == -1, "wrong value %s\n", debugstr_variant(&propset->rgProperties[i].vValue));
+ vartype = VT_I4;
+ }
+
+ ok(V_VT(&propset->rgProperties[i].vValue) == vartype, "%d wrong type %d\n", i, V_VT(&propset->rgProperties[i].vValue));
+ }
+
+ CoTaskMemFree(propidlist.rgPropertyIDs);
+ CoTaskMemFree(propset);
}
IDBProperties_Release(props);
diff --git a/dlls/oledb32/tests/database.c b/dlls/oledb32/tests/database.c
index 421f4258afd..8bdb1f948f4 100644
--- a/dlls/oledb32/tests/database.c
+++ b/dlls/oledb32/tests/database.c
@@ -1039,8 +1039,7 @@ static void test_odbc_provider(void)
CoTaskMemFree(propinfoset);
hr = IDBProperties_GetProperties(props, 1, &propidlist, &propcnt, &propset);
- todo_wine ok(hr == S_OK, "got 0x%08x\n", hr);
- if (hr == S_OK) { /* Remove if, once _GetProperties is implemented */
+ ok(hr == S_OK, "got 0x%08x\n", hr);
ok(propidlist.cPropertyIDs == 14, "got %d\n", propinfoset->cPropertyInfos);
for (i = 0; i < propidlist.cPropertyIDs; i++)
@@ -1050,7 +1049,6 @@ static void test_odbc_provider(void)
propidlist.rgPropertyIDs[i] = propinfoset->rgPropertyInfos[i].dwPropertyID;
}
- }
CoTaskMemFree(propidlist.rgPropertyIDs);
CoTaskMemFree(propset);
--
2.33.0
Nov. 5, 2021
[PATCH v3 4/4] 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 | 60 ++++++++++++++++++++++++++++++++--
dlls/wined3d/cs.c | 16 ++++++++-
dlls/wined3d/directx.c | 7 ++++
dlls/wined3d/wined3d_private.h | 13 ++++++++
6 files changed, 149 insertions(+), 3 deletions(-)
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c
index 7ec30cb4356..8ec59c5cbc3 100644
--- a/dlls/wined3d/adapter_gl.c
+++ b/dlls/wined3d/adapter_gl.c
@@ -4606,6 +4606,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)
@@ -5059,6 +5065,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 8335a030b6b..3e1d63234ec 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_bo_vk *bo_vk;
+
+ if (!(bo_vk = heap_alloc(sizeof(*bo_vk))))
+ 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), bo_vk)))
+ {
+ WARN("Failed to create Vulkan buffer.\n");
+ return false;
+ }
+
+ if (!bo_vk->b.map_ptr)
+ {
+ WARN_(d3d_perf)("BO %p (chunk %p, slab %p) is not persistently mapped.\n",
+ bo_vk, bo_vk->memory ? bo_vk->memory->chunk : NULL, bo_vk->slab);
+
+ if (!wined3d_bo_vk_map(bo_vk, context_vk))
+ ERR("Failed to map bo.\n");
+ }
+
+ addr->buffer_object = (uintptr_t)bo_vk;
+ 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 56069cb9f16..a9beba023de 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;
@@ -1580,12 +1604,44 @@ 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);
+
+ wined3d_context_vk_destroy_bo(context_vk, prev_bo);
+ heap_free(prev_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..ac7799e17b2 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 false;
+ }
+
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 398bd73c5c0..b2a9e1d6958 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -331,6 +331,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)
{
@@ -1642,6 +1644,11 @@ 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_bo_slab_vk_key
{
VkMemoryPropertyFlags memory_type;
@@ -3343,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
{
@@ -3375,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,
@@ -5022,6 +5032,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
@@ -5067,6 +5078,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. 5, 2021
[PATCH v3 3/4] wined3d: Allocate all Vulkan buffer BOs from heap.
by Zebediah Figura
That is, no longer allocate a wined3d_bo_vk as part of the wined3d_buffer_vk
structure.
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/wined3d/buffer.c | 23 +++++++++++++----------
dlls/wined3d/wined3d_private.h | 1 -
2 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index 0a72f19935b..56069cb9f16 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -1440,18 +1440,22 @@ static BOOL wined3d_buffer_vk_create_buffer_object(struct wined3d_buffer_vk *buf
struct wined3d_context_vk *context_vk)
{
struct wined3d_resource *resource = &buffer_vk->b.resource;
+ struct wined3d_bo_vk *bo_vk;
+
+ if (!(bo_vk = heap_alloc(sizeof(*bo_vk))))
+ 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), &buffer_vk->bo)))
+ vk_memory_type_from_access_flags(resource->access, resource->usage), bo_vk)))
{
WARN("Failed to create Vulkan buffer.\n");
return FALSE;
}
list_init(&buffer_vk->b.bo_user.entry);
- list_add_head(&buffer_vk->bo.b.users, &buffer_vk->b.bo_user.entry);
- buffer_vk->b.buffer_object = (uintptr_t)&buffer_vk->bo;
+ list_add_head(&bo_vk->b.users, &buffer_vk->b.bo_user.entry);
+ buffer_vk->b.buffer_object = (uintptr_t)bo_vk;
buffer_invalidate_bo_range(&buffer_vk->b, 0, 0);
return TRUE;
@@ -1495,20 +1499,19 @@ static BOOL wined3d_buffer_vk_prepare_location(struct wined3d_buffer *buffer,
static void wined3d_buffer_vk_unload_location(struct wined3d_buffer *buffer,
struct wined3d_context *context, unsigned int location)
{
+ struct wined3d_bo_vk *bo_vk = (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);
TRACE("buffer %p, context %p, location %s.\n", buffer, context, wined3d_debug_location(location));
switch (location)
{
case WINED3D_LOCATION_BUFFER:
- buffer_vk->b.bo_user.valid = false;
- list_remove(&buffer_vk->b.bo_user.entry);
- wined3d_context_vk_destroy_bo(context_vk, &buffer_vk->bo);
- buffer_vk->bo.vk_buffer = VK_NULL_HANDLE;
- buffer_vk->bo.memory = NULL;
- buffer_vk->b.buffer_object = 0u;
+ buffer->bo_user.valid = false;
+ list_remove(&buffer->bo_user.entry);
+ wined3d_context_vk_destroy_bo(context_vk, bo_vk);
+ heap_free(bo_vk);
+ buffer->buffer_object = 0u;
break;
default:
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index e0cae322179..398bd73c5c0 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -5097,7 +5097,6 @@ struct wined3d_buffer_vk
{
struct wined3d_buffer b;
- struct wined3d_bo_vk bo;
VkDescriptorBufferInfo buffer_info;
uint32_t bind_mask;
};
--
2.33.0
Nov. 5, 2021
[PATCH v3 2/4] 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 | 25 ++++++++++++++++++++++++-
dlls/wined3d/wined3d_private.h | 5 +++++
3 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c
index 2e14972f4d8..8335a030b6b 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..46769be516e 100644
--- a/dlls/wined3d/context_vk.c
+++ b/dlls/wined3d/context_vk.c
@@ -247,16 +247,29 @@ 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)
{
@@ -265,8 +278,11 @@ void *wined3d_allocator_chunk_vk_map(struct wined3d_allocator_chunk_vk *chunk_vk
}
++chunk_vk->c.map_count;
+ map_ptr = chunk_vk->c.map_ptr;
- 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 dd04569d86a..e0cae322179 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -4101,6 +4101,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. 5, 2021
[PATCH v3 1/4] 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 2bd3aa31e49..2e14972f4d8 100644
--- a/dlls/wined3d/adapter_vk.c
+++ b/dlls/wined3d/adapter_vk.c
@@ -1745,7 +1745,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);
@@ -1817,7 +1817,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 8da8a60d28e..dd04569d86a 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -6315,7 +6315,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. 5, 2021
Re: [PATCH] msxml3: Allow DOMDocument in VT_DISPATCH slot for put_output.
by Jefferson Carpenter
On 11/4/2021 9:17 PM, Nikolay Sivov wrote:
>
>
> On 11/4/21 11:58 PM, Jefferson Carpenter wrote:
>> Regarding locking the DOMDocument while it is being written to:
>>
>> It looks like DOMDocument is meant to be used in a single-threaded
>> manner[1], so it should be all right to just grab an interface and not
>> worry about threads attempting to manipulate the document while it is
>> being written to by an mxwriter.
>
> There are freethreaded classes as well.
Ah, Wine uses the same implementation for both, I see.
>
>>
>> For how to lock it, unless anyone has a better idea I think it would
>> work to add an IWineXMLDOMDocumentLock interface with lock() and
>> unlock() methods, and output a FIXME if this interface is unavailable.
> I think your best bet at the moment is to load whole document at once
> from stream, on endDocument. Right way would probably be similar to how
> libxml2 does it - using SAX callbacks to construct DOM tree, and then
> using SAX reader when loading from stream, or writer calling them.
Could do that, but the code would need to be re-written so that nodes
appear as soon as the corresponding SAX methods are called on the
writer. (Nodes are visible as soon as startElement is called).
Did you mean "from string", not "from stream"? The string from
get_output could be passed to loadXML. However struct domdoc doesn't
have an IStream interface (It has IPersistStreamInit) to attach to the
writer, and mxwriter doesn't have a stream interface for the document to
load either.
Doing that actually causes Rise of Legends to be able to load the
mission and the game works if SAXContentHandler_putDocumentLocator
returns S_OK. See the patch I attached on the bug [1]
[1] https://bugs.winehq.org/show_bug.cgi?id=51965
Nov. 4, 2021