Wine-devel
Threads by month
- ----- 2026 -----
- 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
February 2018
- 74 participants
- 746 discussions
19 Feb '18
Without this fix, synthetic tmAveCharWidth value unintentionally affects
SCALE_X calculation.
Signed-off-by: Akihiro Sagawa <sagawa.aki(a)gmail.com>
---
dlls/gdi32/freetype.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
2
1
Signed-off-by: Alex Henrie <alexhenrie24(a)gmail.com>
---
This test has failed on the Windows 8 and Windows 10 testbot VMs since
January 19, most likely because of some Windows update. I wasn't able to
figure out what the seemingly random return codes mean, but they're not
errors.
dlls/schannel/tests/main.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/schannel/tests/main.c b/dlls/schannel/tests/main.c
index fb350d5e62..fc913c14a9 100644
--- a/dlls/schannel/tests/main.c
+++ b/dlls/schannel/tests/main.c
@@ -219,11 +219,11 @@ static void testGetInfo(void)
return;
}
status = pTables->GetInfo(&PackageInfo);
- ok(status == STATUS_SUCCESS ||
+ ok(SUCCEEDED(status) ||
status == SEC_E_UNSUPPORTED_FUNCTION, /* win2k3 */
"status: 0x%x\n", status);
- if (status == STATUS_SUCCESS)
+ if (SUCCEEDED(status))
{
ok(PackageInfo.fCapabilities == LSA_BASE_CAPS ||
PackageInfo.fCapabilities == (LSA_BASE_CAPS|SECPKG_FLAG_APPCONTAINER_PASSTHROUGH),
--
2.16.1
2
1
19 Feb '18
Signed-off-by: Alex Henrie <alexhenrie24(a)gmail.com>
---
This resolves a Coverity warning.
dlls/shlwapi/tests/Makefile.in | 2 +-
dlls/shlwapi/tests/ordinal.c | 205 +++--------------------------------------
2 files changed, 16 insertions(+), 191 deletions(-)
diff --git a/dlls/shlwapi/tests/Makefile.in b/dlls/shlwapi/tests/Makefile.in
index 7155f38c4a..6a5e71b0f3 100644
--- a/dlls/shlwapi/tests/Makefile.in
+++ b/dlls/shlwapi/tests/Makefile.in
@@ -1,5 +1,5 @@
TESTDLL = shlwapi.dll
-IMPORTS = shlwapi user32 ole32 oleaut32 advapi32
+IMPORTS = shlwapi user32 ole32 oleaut32 advapi32 shell32 mlang
C_SRCS = \
assoc.c \
diff --git a/dlls/shlwapi/tests/ordinal.c b/dlls/shlwapi/tests/ordinal.c
index 004c75da3f..f192849cd4 100644
--- a/dlls/shlwapi/tests/ordinal.c
+++ b/dlls/shlwapi/tests/ordinal.c
@@ -36,8 +36,6 @@
/* Function ptrs for ordinal calls */
static HMODULE hShlwapi;
-static BOOL is_win2k_and_lower;
-static BOOL is_win9x;
static int (WINAPI *pSHSearchMapInt)(const int*,const int*,int,int);
static HRESULT (WINAPI *pGetAcceptLanguagesA)(LPSTR,LPDWORD);
@@ -89,12 +87,6 @@ typedef struct SHELL_USER_PERMISSION {
static SECURITY_DESCRIPTOR* (WINAPI *pGetShellSecurityDescriptor)(const SHELL_USER_PERMISSION**,int);
-static HMODULE hmlang;
-static HRESULT (WINAPI *pLcidToRfc1766A)(LCID, LPSTR, INT);
-
-static HMODULE hshell32;
-static HRESULT (WINAPI *pSHGetDesktopFolder)(IShellFolder**);
-
static const CHAR ie_international[] = {
'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\',
@@ -207,11 +199,6 @@ static void test_GetAcceptLanguagesA(void)
LPCSTR entry;
INT i = 0;
- if (!pGetAcceptLanguagesA) {
- win_skip("GetAcceptLanguagesA is not available\n");
- return;
- }
-
lcid = GetUserDefaultLCID();
/* Get the original Value */
@@ -257,10 +244,8 @@ static void test_GetAcceptLanguagesA(void)
if (lstrcmpA(buffer, language)) {
/* some windows versions use "lang" or "lang-country" as default */
language[0] = 0;
- if (pLcidToRfc1766A) {
- hr = pLcidToRfc1766A(lcid, language, sizeof(language));
- ok(hr == S_OK, "LcidToRfc1766A returned 0x%x and %s\n", hr, language);
- }
+ hr = LcidToRfc1766A(lcid, language, sizeof(language));
+ ok(hr == S_OK, "LcidToRfc1766A returned 0x%x and %s\n", hr, language);
}
ok(!lstrcmpA(buffer, language),
@@ -714,40 +699,20 @@ static void test_GetShellSecurityDescriptor(void)
&supCurrentUserFull, &supEveryoneDenied,
};
SECURITY_DESCRIPTOR* psd;
- void *pChrCmpIW = GetProcAddress(hShlwapi, "ChrCmpIW");
- if(!pGetShellSecurityDescriptor)
+ if(!pGetShellSecurityDescriptor) /* vista and later */
{
win_skip("GetShellSecurityDescriptor not available\n");
return;
}
- if(pChrCmpIW && pChrCmpIW == pGetShellSecurityDescriptor) /* win2k */
- {
- win_skip("Skipping for GetShellSecurityDescriptor, same ordinal used for ChrCmpIW\n");
- return;
- }
-
psd = pGetShellSecurityDescriptor(NULL, 2);
- ok(psd==NULL ||
- broken(psd==INVALID_HANDLE_VALUE), /* IE5 */
- "GetShellSecurityDescriptor should fail\n");
+ ok(psd==NULL, "GetShellSecurityDescriptor should fail\n");
psd = pGetShellSecurityDescriptor(rgsup, 0);
ok(psd==NULL, "GetShellSecurityDescriptor should fail, got %p\n", psd);
SetLastError(0xdeadbeef);
psd = pGetShellSecurityDescriptor(rgsup, 2);
- if (psd == NULL && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
- {
- /* The previous calls to GetShellSecurityDescriptor don't set the last error */
- win_skip("GetShellSecurityDescriptor is not implemented\n");
- return;
- }
- if (psd == INVALID_HANDLE_VALUE)
- {
- win_skip("GetShellSecurityDescriptor is broken on IE5\n");
- return;
- }
ok(psd!=NULL, "GetShellSecurityDescriptor failed\n");
if (psd!=NULL)
{
@@ -822,9 +787,6 @@ static void test_SHPackDispParams(void)
VARIANT vars[10];
HRESULT hres;
- if(!pSHPackDispParams)
- win_skip("SHPackSidpParams not available\n");
-
memset(¶ms, 0xc0, sizeof(params));
memset(vars, 0xc0, sizeof(vars));
hres = pSHPackDispParams(¶ms, vars, 1, VT_I4, 0xdeadbeef);
@@ -1495,12 +1457,6 @@ static void test_IConnectionPoint(void)
DISPPARAMS params;
VARIANT vars[10];
- if (!pIConnectionPoint_SimpleInvoke || !pConnectToConnectionPoint)
- {
- win_skip("IConnectionPoint Apis not present\n");
- return;
- }
-
container = HeapAlloc(GetProcessHeap(),0,sizeof(Contain));
container->IConnectionPointContainer_iface.lpVtbl = &contain_vtbl;
container->refCount = 1;
@@ -1519,18 +1475,13 @@ static void test_IConnectionPoint(void)
rc = pIConnectionPoint_SimpleInvoke(point,0xa0,NULL);
ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
- if (pSHPackDispParams)
- {
- memset(¶ms, 0xc0, sizeof(params));
- memset(vars, 0xc0, sizeof(vars));
- rc = pSHPackDispParams(¶ms, vars, 2, VT_I4, 0xdeadbeef, VT_BSTR, 0xdeadcafe);
- ok(rc == S_OK, "SHPackDispParams failed: %08x\n", rc);
+ memset(¶ms, 0xc0, sizeof(params));
+ memset(vars, 0xc0, sizeof(vars));
+ rc = pSHPackDispParams(¶ms, vars, 2, VT_I4, 0xdeadbeef, VT_BSTR, 0xdeadcafe);
+ ok(rc == S_OK, "SHPackDispParams failed: %08x\n", rc);
- rc = pIConnectionPoint_SimpleInvoke(point,0xa1,¶ms);
- ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
- }
- else
- win_skip("pSHPackDispParams not present\n");
+ rc = pIConnectionPoint_SimpleInvoke(point,0xa1,¶ms);
+ ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
rc = pConnectToConnectionPoint(NULL, &IID_NULL, FALSE, (IUnknown*)container, &cookie, NULL);
ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc);
@@ -1634,12 +1585,6 @@ static void test_SHPropertyBag_ReadLONG(void)
LONG out;
static const WCHAR szName1[] = {'n','a','m','e','1',0};
- if (!pSHPropertyBag_ReadLONG)
- {
- win_skip("SHPropertyBag_ReadLONG not present\n");
- return;
- }
-
pb = HeapAlloc(GetProcessHeap(),0,sizeof(PropBag));
pb->refCount = 1;
pb->IPropertyBag_iface.lpVtbl = &prop_vtbl;
@@ -1665,12 +1610,6 @@ static void test_SHSetWindowBits(void)
DWORD style, styleold;
WNDCLASSA clsA;
- if(!pSHSetWindowBits)
- {
- win_skip("SHSetWindowBits is not available\n");
- return;
- }
-
clsA.style = 0;
clsA.lpfnWndProc = DefWindowProcA;
clsA.cbClsExtra = 0;
@@ -1691,8 +1630,7 @@ static void test_SHSetWindowBits(void)
SetLastError(0xdeadbeef);
style = pSHSetWindowBits(NULL, GWL_STYLE, 0, 0);
ok(style == 0, "expected 0 retval, got %d\n", style);
- ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE ||
- broken(GetLastError() == 0xdeadbeef), /* Win9x/WinMe */
+ ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE,
"expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
/* zero mask, zero flags */
@@ -1742,12 +1680,6 @@ static void test_SHFormatDateTimeA(void)
DWORD flags;
INT ret;
- if(!pSHFormatDateTimeA)
- {
- win_skip("pSHFormatDateTimeA isn't available\n");
- return;
- }
-
if (0)
{
/* crashes on native */
@@ -1792,8 +1724,7 @@ if (0)
SetLastError(0xdeadbeef);
ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
- ok(GetLastError() == 0xdeadbeef ||
- broken(GetLastError() == ERROR_INVALID_FLAGS), /* Win9x/WinMe */
+ ok(GetLastError() == 0xdeadbeef,
"expected 0xdeadbeef, got %d\n", GetLastError());
/* now check returned strings */
@@ -1904,12 +1835,6 @@ static void test_SHFormatDateTimeW(void)
#define UNICODE_LTR_MARK 0x200e
#define UNICODE_RTL_MARK 0x200f
- if(!pSHFormatDateTimeW)
- {
- win_skip("pSHFormatDateTimeW isn't available\n");
- return;
- }
-
if (0)
{
/* crashes on native */
@@ -1955,8 +1880,7 @@ if (0)
ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff),
"expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
- ok(GetLastError() == 0xdeadbeef ||
- broken(GetLastError() == ERROR_INVALID_FLAGS), /* Win9x/WinMe/NT4 */
+ ok(GetLastError() == 0xdeadbeef,
"expected 0xdeadbeef, got %d\n", GetLastError());
/* now check returned strings */
@@ -1966,11 +1890,6 @@ if (0)
"expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret);
SetLastError(0xdeadbeef);
ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
- if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
- {
- win_skip("Needed W-functions are not implemented\n");
- return;
- }
ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret);
ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
@@ -2118,24 +2037,11 @@ static void test_SHGetObjectCompatFlags(void)
};
static const char compat_path[] = "Software\\Microsoft\\Windows\\CurrentVersion\\ShellCompatibility\\Objects";
- void *pColorAdjustLuma = GetProcAddress(hShlwapi, "ColorAdjustLuma");
CHAR keyA[39]; /* {CLSID} */
HKEY root;
DWORD ret;
int i;
- if (!pSHGetObjectCompatFlags)
- {
- win_skip("SHGetObjectCompatFlags isn't available\n");
- return;
- }
-
- if (pColorAdjustLuma && pColorAdjustLuma == pSHGetObjectCompatFlags) /* win2k */
- {
- win_skip("Skipping SHGetObjectCompatFlags, same ordinal used for ColorAdjustLuma\n");
- return;
- }
-
/* null args */
ret = pSHGetObjectCompatFlags(NULL, NULL);
ok(ret == 0, "got %d\n", ret);
@@ -2392,14 +2298,6 @@ static void test_IUnknown_QueryServiceExec(void)
call_trace_t trace_expected;
HRESULT hr;
- /* on <=W2K platforms same ordinal used for another export with different
- prototype, so skipping using this indirect condition */
- if (is_win2k_and_lower)
- {
- win_skip("IUnknown_QueryServiceExec is not available\n");
- return;
- }
-
provider = IServiceProviderImpl_Construct();
/* null source pointer */
@@ -2509,14 +2407,6 @@ static void test_IUnknown_ProfferService(void)
HRESULT hr;
DWORD cookie;
- /* on <=W2K platforms same ordinal used for another export with different
- prototype, so skipping using this indirect condition */
- if (is_win2k_and_lower)
- {
- win_skip("IUnknown_ProfferService is not available\n");
- return;
- }
-
provider = IServiceProviderImpl_Construct();
proff = IProfferServiceImpl_Construct();
@@ -2580,12 +2470,6 @@ static void test_SHCreateWorkerWindowA(void)
LONG_PTR ret;
BOOL res;
- if (is_win2k_and_lower)
- {
- win_skip("SHCreateWorkerWindowA not available\n");
- return;
- }
-
hwnd = pSHCreateWorkerWindowA(0, NULL, 0, 0, 0, 0);
ok(hwnd != 0, "expected window\n");
@@ -2746,7 +2630,7 @@ static void test_SHIShellFolder_EnumObjects(void)
HRESULT hres;
IShellFolder *folder;
- if(!pSHIShellFolder_EnumObjects || is_win2k_and_lower){
+ if(!pSHIShellFolder_EnumObjects){ /* win7 and later */
win_skip("SHIShellFolder_EnumObjects not available\n");
return;
}
@@ -2763,7 +2647,7 @@ static void test_SHIShellFolder_EnumObjects(void)
ok(enm == (IEnumIDList*)0xcafebabe, "Didn't get expected enumerator location, instead: %p\n", enm);
/* SHIShellFolder_EnumObjects isn't strict about the IShellFolder object */
- hres = pSHGetDesktopFolder(&folder);
+ hres = SHGetDesktopFolder(&folder);
ok(hres == S_OK, "SHGetDesktopFolder failed: 0x%08x\n", hres);
enm = NULL;
@@ -2832,11 +2716,6 @@ static void test_SHGetIniString(void)
static const WCHAR testpathW[] = {'C',':','\\','t','e','s','t','.','i','n','i',0};
WCHAR pathW[MAX_PATH];
- if(!pSHGetIniStringW || is_win2k_and_lower){
- win_skip("SHGetIniStringW is not available\n");
- return;
- }
-
lstrcpyW(pathW, testpathW);
if (!write_inifile(pathW))
@@ -2887,11 +2766,6 @@ static void test_SHSetIniString(void)
static const WCHAR NewKeyW[] = {'N','e','w','K','e','y',0};
static const WCHAR AValueW[] = {'A','V','a','l','u','e',0};
- if(!pSHSetIniStringW || is_win2k_and_lower){
- win_skip("SHSetIniStringW is not available\n");
- return;
- }
-
if (!write_inifile(TestIniW))
return;
@@ -2936,30 +2810,10 @@ static void test_SHGetShellKey(void)
static const WCHAR ShellFoldersW[] = { 'S','h','e','l','l',' ','F','o','l','d','e','r','s',0 };
static const WCHAR WineTestW[] = { 'W','i','n','e','T','e','s','t',0 };
- void *pPathBuildRootW = GetProcAddress(hShlwapi, "PathBuildRootW");
DWORD *alloc_data, data, size;
HKEY hkey;
HRESULT hres;
- if (!pSHGetShellKey)
- {
- win_skip("SHGetShellKey(ordinal 491) isn't available\n");
- return;
- }
-
- /* some win2k */
- if (pPathBuildRootW && pPathBuildRootW == pSHGetShellKey)
- {
- win_skip("SHGetShellKey(ordinal 491) used for PathBuildRootW\n");
- return;
- }
-
- if (is_win9x || is_win2k_and_lower)
- {
- win_skip("Ordinal 491 used for another call, skipping SHGetShellKey tests\n");
- return;
- }
-
/* Vista+ limits SHKEY enumeration values */
SetLastError(0xdeadbeef);
hkey = pSHGetShellKey(SHKEY_Key_Explorer, ShellFoldersW, FALSE);
@@ -2998,12 +2852,6 @@ static void test_SHGetShellKey(void)
ok(hkey != NULL, "Can't create key\n");
RegCloseKey(hkey);
- if (!pSKGetValueW || !pSKSetValueW || !pSKDeleteValueW || !pSKAllocValueW)
- {
- win_skip("SKGetValueW, SKSetValueW, SKDeleteValueW or SKAllocValueW not available\n");
- return;
- }
-
size = sizeof(data);
hres = pSKGetValueW(SHKEY_Root_HKLM, WineTestW, NULL, NULL, &data, &size);
ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "hres = %x\n", hres);
@@ -3091,12 +2939,6 @@ static void test_SHSetParentHwnd(void)
HWND hwnd, hwnd2, ret;
DWORD style;
- if (!pSHSetParentHwnd)
- {
- win_skip("SHSetParentHwnd not available\n");
- return;
- }
-
hwnd = CreateWindowA("Button", "", WS_VISIBLE, 0, 0, 10, 10, NULL, NULL, NULL, NULL);
ok(hwnd != NULL, "got %p\n", hwnd);
@@ -3271,14 +3113,6 @@ START_TEST(ordinal)
int argc;
hShlwapi = GetModuleHandleA("shlwapi.dll");
- is_win2k_and_lower = GetProcAddress(hShlwapi, "StrChrNW") == 0;
- is_win9x = GetProcAddress(hShlwapi, (LPSTR)99) == 0; /* StrCpyNXA */
-
- /* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
- if(!GetProcAddress(hShlwapi, "SHCreateStreamOnFileEx")){
- win_skip("Too old shlwapi version\n");
- return;
- }
init_pointers();
@@ -3293,12 +3127,6 @@ START_TEST(ordinal)
return;
}
- hmlang = LoadLibraryA("mlang.dll");
- pLcidToRfc1766A = (void *)GetProcAddress(hmlang, "LcidToRfc1766A");
-
- hshell32 = LoadLibraryA("shell32.dll");
- pSHGetDesktopFolder = (void *)GetProcAddress(hshell32, "SHGetDesktopFolder");
-
test_GetAcceptLanguagesA();
test_SHSearchMapInt();
test_alloc_shared(argc, argv);
@@ -3321,7 +3149,4 @@ START_TEST(ordinal)
test_SHSetParentHwnd();
test_IUnknown_GetClassID();
test_DllGetVersion();
-
- FreeLibrary(hshell32);
- FreeLibrary(hmlang);
}
--
2.16.1
1
0
[PATCH 2/2] testbot: Add some traces to help diagnose scheduler issues.
by Francois Gouget 19 Feb '18
by Francois Gouget 19 Feb '18
19 Feb '18
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/lib/WineTestBot/Jobs.pm | 59 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 59 insertions(+)
diff --git a/testbot/lib/WineTestBot/Jobs.pm b/testbot/lib/WineTestBot/Jobs.pm
index 036222110..9a0f8bc39 100644
--- a/testbot/lib/WineTestBot/Jobs.pm
+++ b/testbot/lib/WineTestBot/Jobs.pm
@@ -1012,6 +1012,63 @@ sub _SacrificeVM($$$)
return 1;
}
+sub _DumpHostCounters($$)
+{
+ my ($Sched, $VM) = @_;
+ my $Host = _GetSchedHost($Sched, $VM);
+ return if ($Host->{dumpedcounters});
+
+ my $Counters = "";
+ if ($Host->{active})
+ {
+ $Counters .= " active=$Host->{active}/$Host->{MaxActiveVMs}";
+ }
+ if ($Host->{idle})
+ {
+ $Counters .= " idle=$Host->{idle}". ($Host->{queued} ? "" : "/$Host->{MaxVMsWhenIdle}");
+ }
+ if ($Host->{reverting})
+ {
+ $Counters .= " reverting=$Host->{reverting}/". _GetMaxReverts($Host);
+ }
+ for my $Counter ("sleeping", "running", "dirty", "queued")
+ {
+ $Counters .= " $Counter=$Host->{$Counter}" if ($Host->{$Counter});
+ }
+ my $HostKey = $VM->GetHost();
+ my $PrettyHost = ($PrettyHostNames ? $PrettyHostNames->{$HostKey} : "") ||
+ $HostKey;
+ require WineTestBot::Log;
+ WineTestBot::Log::LogMsg("$PrettyHost:$Counters\n") if ($Counters);
+
+ $Host->{dumpedcounters} = 1;
+}
+
+sub _DumpHostVMs($$$$)
+{
+ my ($Sched, $VM, $SortedNeededVMs, $NeededVMs) = @_;
+ my $Host = _GetSchedHost($Sched, $VM);
+ return if ($Host->{dumpedvms});
+
+ _DumpHostCounters($Sched, $VM);
+
+ my @VMInfo;
+ my $HostKey = $VM->GetHost();
+ foreach my $VMKey (@$SortedNeededVMs)
+ {
+ $VM = $Sched->{VMs}->GetItem($VMKey);
+ next if ($VM->GetHost() ne $HostKey);
+
+ push @VMInfo, join(":", "$VMKey(". $VM->Status .")", $NeededVMs->{$VMKey}->[0], $NeededVMs->{$VMKey}->[1], $NeededVMs->{$VMKey}->[2]);
+ }
+ my $PrettyHost = ($PrettyHostNames ? $PrettyHostNames->{$HostKey} : "") ||
+ $HostKey;
+ require WineTestBot::Log;
+ WineTestBot::Log::LogMsg("$PrettyHost: @VMInfo\n");
+
+ $Host->{dumpedvms} = 1;
+}
+
sub _RevertVMs($$)
{
my ($Sched, $NeededVMs) = @_;
@@ -1027,6 +1084,7 @@ sub _RevertVMs($$)
# Check if the host has reached its reverting VMs limit
my $Host = _GetSchedHost($Sched, $VM);
next if ($Host->{reverting} >= _GetMaxReverts($Host));
+ _DumpHostCounters($Sched, $VM);
# Skip this VM if the previous step's tasks are not about to run yet
next if (_HasMissingDependencies($Sched, $NeededVMs, $VMKey));
@@ -1071,6 +1129,7 @@ sub _RevertVMs($$)
$NeedsSacrifice = ($FutureActive > $Host->{MaxActiveVMs});
}
+ _DumpHostVMs($Sched, $VM, \@SortedNeededVMs, $NeededVMs);
if ($NeedsSacrifice)
{
# Find an active VM to sacrifice so we can revert this VM in the next
--
2.16.1
1
0
19 Feb '18
- The new scheduler splits the work into smaller steps: assessing the
current situation, starting tasks on idle VMs and building a list of
needed VMs, reverting the VMs, powering off the remaining VMs,
updating the activity records. Each part can be analyzed
independently. It uses the $Sched structure to pass information
between these functions.
- Sometimes a VM that no Task needs must be powered off in order to be
able to prepare a VM that is needed. The job of picking which VM to
sacrifice is now delegated to _SacrificeVM().
- The scheduler used to handle each VM host independently. As a result
it was unable to prepare a VM for the 'next step' if that VM was on
another VM host. The lack of a global picture also made many other
extensions impossible. The new scheduler handles scheduling on all
VM hosts at the same time, thus solving this issue.
- This and other improvements mean the scheduler no longer needs to loop
over the jobs and tasks multiple times.
- In order to respect the per-VM-host limits the scheduler stores the
host-related counters and limits in the $Sched->{hosts} table.
- The scheduler also used to build multiple lists of VMs to revert
depending on whether they were needed now, for the next step, or for
future jobs. The new scheduler builds a single prioritised list of
VMs to revert which can be handled in one go. It also keeps more
information so it can better decide which VM to prepare next.
- The scheduler can now also prepare VMs for the 'next step' earlier,
thus making it more likely they will be ready in time.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/lib/WineTestBot/Jobs.pm | 914 ++++++++++++++++++++++++++++------------
1 file changed, 637 insertions(+), 277 deletions(-)
diff --git a/testbot/lib/WineTestBot/Jobs.pm b/testbot/lib/WineTestBot/Jobs.pm
index 4ed6e03ff..036222110 100644
--- a/testbot/lib/WineTestBot/Jobs.pm
+++ b/testbot/lib/WineTestBot/Jobs.pm
@@ -429,6 +429,26 @@ sub CompareJobPriority
return $a->Priority <=> $b->Priority || $a->Id <=> $b->Id;
}
+=pod
+=over 12
+
+=item C<CheckJobs()>
+
+Goes through the list of Jobs and updates their status. As a side-effect this
+detects failed builds, dead child processes, etc.
+
+=back
+=cut
+
+sub CheckJobs()
+{
+ my $Jobs = CreateJobs();
+ $Jobs->AddFilter("Status", ["queued", "running"]);
+ map { $_->UpdateStatus(); } @{$Jobs->GetItems()};
+
+ return undef;
+}
+
sub min(@)
{
my $m = shift @_;
@@ -436,304 +456,658 @@ sub min(@)
return $m;
}
+sub _GetSchedHost($$)
+{
+ my ($Sched, $VM) = @_;
+
+ my $HostKey = $VM->GetHost();
+ if (!$Sched->{hosts}->{$HostKey})
+ {
+ $Sched->{hosts}->{$HostKey} = {
+ active => 0,
+ idle => 0,
+ reverting => 0,
+ sleeping => 0,
+ running => 0,
+ dirty => 0,
+ MaxRevertingVMs => $MaxRevertingVMs,
+ MaxRevertsWhileRunningVMs => $MaxRevertsWhileRunningVMs,
+ MaxActiveVMs => $MaxActiveVMs,
+ MaxVMsWhenIdle => $MaxVMsWhenIdle,
+ };
+ }
+ return $Sched->{hosts}->{$HostKey};
+}
+
+sub _GetMaxReverts($)
+{
+ my ($Host) = @_;
+ return ($Host->{running} > 0) ?
+ $Host->{MaxRevertsWhileRunningVMs} :
+ $Host->{MaxRevertingVMs};
+}
+
=pod
=over 12
-=item C<ScheduleOnHost()>
+=item C<_CanScheduleOnVM()>
-This manages the VMs and WineTestBot::Task objects corresponding to the
-hypervisors of a given host. To stay within the host's resource limits the
-scheduler must take the following constraints into account:
-=over
+Checks if a task or VM operation can be performed on the specified VM.
-=item *
+=back
+=cut
-Jobs should be run in decreasing order of priority.
+sub _CanScheduleOnVM($$)
+{
+ my ($Sched, $VM) = @_;
-=item *
+ return 1 if ($VM->Status eq "off");
-A Job's Steps must be run in sequential order.
+ # If the VM is busy it cannot be taken over for a new task
+ my $VMKey = $VM->GetKey();
+ return 0 if ($Sched->{busyvms}->{$VMKey});
+
+ # A process may be working on the VM even though it is not busy (e.g. if it
+ # is sleeping). In that case just wait.
+ return !$VM->ChildPid;
+}
+
+=pod
+=over 12
+
+=item C<_CheckAndClassifyVMs()>
+
+Checks the VMs state consistency, counts the VMs in each state and classifies
+them.
+
+=over
=item *
-A Step's tasks can be run in parallel but only one task can be running in a VM
-at a given time. Also a VM must be prepared before it can run its task, see the
-VM Statuses.
+Checks that each VM's state is consistent and fixes the VM state if not. For
+instance, if Status == running then the VM should have a child process. If
+there is no such process, or if it died, then the VM should be brought back
+to a coherent state, typically by marking it dirty so it is either powered off
+or reverted.
=item *
-The number of active VMs on the host must be kept under $MaxActiveVMs. This
-includes any VM using resources, including those that are being reverted. The
-rational behind this limit is that the host may not be able to run more VMs
-simultaneously, typically due to memory or CPU constraints. Also note that
-this limit must be respected even if there is more than one hypervisor running
-on the host.
+Counts the VMs in each state so the scheduler can respect the limits put on the
+number of simultaneous active VMs, reverting VMs, and so on.
=item *
-The number of VMs being reverted on the host at a given time must be kept under
-$MaxRevertingVMs, or $MaxRevertsWhileRunningVMs if some VMs are currently
-running tests. This may be set to 1 in case the hypervisor gets confused when
-reverting too many VMs at once.
+Puts the VMs in one of three sets:
+- The set of busyvms.
+ This is the set of VMs that are doing something important, for instance
+ running a Task, and should not be messed with.
+- The set of lambvms.
+ This is the set of VMs that use resources (they are powered on), but are
+ not doing anything important (idle, sleeping and dirty VMs). If the scheduler
+ is hitting the limits but still needs to power on one more VM, it can power
+ off one of these to make room.
+- The set of powered off VMs.
+ These are the VMs which are in neither the busyvms nor the lambvms set. Since
+ they are powered off they are not using resources.
=item *
-Once there are no jobs to run anymore the scheduler can prepare up to
-$MaxVMsWhenIdle VMs (or $MaxActiveVMs if not set) for future jobs.
-This can be set to 0 to minimize the TestBot resource usage when idle.
-This can also be set to a value greater than $MaxActiveVMs. Then only
-$MaxActiveVMs tasks will be run simultaneously but the extra idle VMs will be
-kept on standby so they are ready when their turn comes.
+Each VM is given a priority describing the likelihood that it will be needed
+by a future job. When no other VM is running this can be used to decide which
+VMs to start in advance.
-=cut
+=back
=back
=cut
-sub ScheduleOnHost($$$$)
+sub _CheckAndClassifyVMs()
{
- my ($ScopeObject, $SortedJobs, $Hypervisors, $Records) = @_;
-
- my $HostVMs = CreateVMs($ScopeObject);
- $HostVMs->FilterEnabledRole();
- $HostVMs->FilterHypervisors($Hypervisors);
+ my $Sched = {
+ VMs => CreateVMs(),
+ hosts => {},
+ busyvms => {},
+ lambvms=> {},
+ nicefuture => {},
+ runnable => 0,
+ queued => 0,
+ recordgroups => CreateRecordGroups(),
+ };
+ $Sched->{recordgroup} = $Sched->{recordgroups}->Add();
+ $Sched->{records} = $Sched->{recordgroup}->Records;
+ # Save the new RecordGroup now so its Id is lower than those of the groups
+ # created by the scripts called from the scheduler.
+ $Sched->{recordgroups}->Save();
+ my $FoundVMErrors;
# Count the VMs that are 'active', that is, that use resources on the host,
# and those that are reverting. Also build a prioritized list of those that
# are ready to run tests: the idle ones.
- my ($RevertingCount, $RunningCount, $IdleCount) = (0, 0, 0);
- my (%VMPriorities, %IdleVMs, @DirtyVMs);
- foreach my $VM (@{$HostVMs->GetItems()})
+ foreach my $VM (@{$Sched->{VMs}->GetItems()})
{
my $VMKey = $VM->GetKey();
- my $VMStatus = $VM->Status;
- if ($VMStatus eq "reverting")
+ if (!$VM->HasEnabledRole())
{
- $RevertingCount++;
+ # Don't schedule anything on this VM and otherwise ignore it
+ $Sched->{busyvms}->{$VMKey} = 1;
+ next;
}
- elsif ($VMStatus eq "running")
- {
- $RunningCount++;
- }
- elsif ($VMStatus eq "offline")
+
+ my $Host = _GetSchedHost($Sched, $VM);
+ if ($VM->HasRunningChild())
{
- if (!$VM->HasRunningChild())
+ if ($VM->Status =~ /^(?:dirty|running|reverting)$/)
{
- $VM->RecordResult($Records, "boterror process died");
- my $ErrMessage = $VM->RunMonitor();
- return $ErrMessage if (defined $ErrMessage);
+ $Sched->{busyvms}->{$VMKey} = 1;
+ $Host->{$VM->Status}++;
+ $Host->{active}++;
+ }
+ elsif ($VM->Status eq "sleeping")
+ {
+ # Note that in the case of powered off VM snapshots, a sleeping VM is
+ # in fact booting up thus taking CPU and I/O resources.
+ # So don't count it as idle.
+ $Sched->{lambvms}->{$VMKey} = 1;
+ $Host->{sleeping}++;
+ $Host->{active}++;
+ }
+ elsif ($VM->Status eq "offline")
+ {
+ # The VM cannot be used until it comes back online
+ $Sched->{busyvms}->{$VMKey} = 1;
+ }
+ elsif ($VM->Status eq "maintenance")
+ {
+ # Maintenance VMs should not have a child process!
+ $FoundVMErrors = 1;
+ $VM->KillChild();
+ $VM->Save();
+ $VM->RecordResult($Sched->{records}, "boterror unexpected process");
+ # And the scheduler should not touch them
+ $Sched->{busyvms}->{$VMKey} = 1;
+ }
+ elsif ($VM->Status =~ /^(?:idle|off)$/)
+ {
+ # idle and off VMs should not have a child process!
+ # Mark the VM dirty so a poweroff or revert brings it to a known state.
+ $FoundVMErrors = 1;
+ $VM->KillChild();
+ $VM->Status("dirty");
+ $VM->Save();
+ $VM->RecordResult($Sched->{records}, "boterror unexpected process");
+ $Sched->{lambvms}->{$VMKey} = 1;
+ $Host->{dirty}++;
+ $Host->{active}++;
+ }
+ else
+ {
+ require WineTestBot::Log;
+ WineTestBot::Log::LogMsg("Unexpected $VMKey status ". $VM->Status ."\n");
+ $FoundVMErrors = 1;
+ # Don't interfere with this VM
+ $Sched->{busyvms}->{$VMKey} = 1;
}
}
else
{
- my $Priority = $VM->Type eq "build" ? 10 :
- $VM->Role ne "base" ? 0 :
- $VM->Type eq "win32" ? 1 : 2;
- $VMPriorities{$VMKey} = $Priority;
-
- # Consider sleeping VMs to be 'almost idle'. We will check their real
- # status before starting a job on them anyway. But if there is no such
- # job, then they are expandable just like idle VMs.
- if ($VMStatus eq "idle" || $VMStatus eq "sleeping")
+ if (defined $VM->ChildPid or
+ $VM->Status =~ /^(?:running|reverting|sleeping)$/)
{
- $IdleCount++;
- $IdleVMs{$VMKey} = 1;
+ # The VM is missing its child process or it died unexpectedly. Mark
+ # the VM dirty so a revert or shutdown brings it back to a known state.
+ $FoundVMErrors = 1;
+ $VM->ChildPid(undef);
+ $VM->Status("dirty");
+ $VM->Save();
+ $VM->RecordResult($Sched->{records}, "boterror process died");
+ $Sched->{lambvms}->{$VMKey} = 1;
+ $Host->{dirty}++;
+ $Host->{active}++;
}
- elsif ($VMStatus eq "dirty")
+ elsif ($VM->Status =~ /^(?:dirty|idle)$/)
{
- push @DirtyVMs, $VMKey;
+ $Sched->{lambvms}->{$VMKey} = 1;
+ $Host->{$VM->Status}++;
+ $Host->{active}++;
}
+ elsif ($VM->Status eq "offline")
+ {
+ my $ErrMessage = $VM->RunMonitor();
+ return ($ErrMessage, undef) if (defined $ErrMessage);
+ # Ignore the VM for this round since we cannot use it
+ $Sched->{busyvms}->{$VMKey} = 1;
+ }
+ elsif ($VM->Status eq "maintenance")
+ {
+ # Don't touch the VM while the administrator is working on it
+ $Sched->{busyvms}->{$VMKey} = 1;
+ }
+ elsif ($VM->Status ne "off")
+ {
+ require WineTestBot::Log;
+ WineTestBot::Log::LogMsg("Unexpected $VMKey status ". $VM->Status ."\n");
+ $FoundVMErrors = 1;
+ # Don't interfere with this VM
+ $Sched->{busyvms}->{$VMKey} = 1;
+ }
+ # Note that off VMs are neither in busyvms nor lambvms
}
+
+ $Sched->{nicefuture}->{$VMKey} =
+ ($VM->Role eq "base" ? 0 :
+ $VM->Role eq "winetest" ? 10 :
+ 20) + # extra
+ ($VM->Type eq "build" ? 0 :
+ $VM->Type eq "win64" ? 1 :
+ 2); # win32
+ }
+
+ # If a VM was in an inconsistent state, update the jobs status fields before
+ # continuing with the scheduling.
+ CheckJobs() if ($FoundVMErrors);
+
+ return (undef, $Sched);
+}
+
+=pod
+=over 12
+
+=item C<_AddNeededVM()>
+
+Adds the specified VM to the list of VMs needed by queued tasks, together with
+priority information. The priority information is stored in an array which
+contains:
+
+=over
+
+=item [0]
+
+The VM's position in the Jobs list. Newer jobs give precedence to older ones.
+Note that the position within a job ($Step->No and $Task->No) does not matter.
+What counts is getting the job results to the developer.
+
+=item [1]
+
+The VM Status: dirty VMs are given a small priority boost since they are
+likely to already be in the host's memory.
+
+=item [2]
+
+The number of Tasks that need the VM. Give priority to VMs that are needed by
+more Tasks so we don't end up in a situation where all the tasks need the same
+VM, which cannot be parallelized.
+
+=item [3]
+
+If the VM is needed for a 'next step', then this lists its dependencies.
+The dependencies are the VMs that are still needed by a task in the current
+step. If any VM in the dependencies list is not yet being prepared to run
+a task, then it is too early to start preparing this VM for the next step.
+
+=back
+
+=back
+=cut
+
+sub _AddNeededVM($$$;$)
+{
+ my ($NeededVMs, $VM, $Niceness, $Dependencies) = @_;
+
+ my $VMKey = $VM->GetKey();
+ if (!$NeededVMs->{$VMKey})
+ {
+ my $Hot = ($VM->Status ne "off") ? 1 : 0;
+ my $PendingReverts = ($VM->Status !~ /^(?:idle|reverting|sleeping)$/) ? 1 : 0;
+ $NeededVMs->{$VMKey} = [$Niceness, $Hot, $PendingReverts, $Dependencies];
+ return 1;
}
- # It usually takes longer to revert a VM than to run a test. So readyness
- # (idleness) trumps the Job priority and thus we start jobs on the idle VMs
- # right away. Then we build a prioritized list of VMs to revert.
- my (%VMsToRevert, @VMsNext);
- my ($RevertNiceness, $SleepingCount) = (0, 0);
- foreach my $Job (@$SortedJobs)
+ # One more task needs this VM
+ $NeededVMs->{$VMKey}->[2]++;
+
+ # Although we process the jobs in decreasing priority order, the VM may
+ # have been added for a 'next step' task and thus with a much increased
+ # niceness and dependencies compared to the jobs that follow.
+ if ($Niceness < $NeededVMs->{$VMKey}->[0])
+ {
+ $NeededVMs->{$VMKey}->[0] = $Niceness;
+ $NeededVMs->{$VMKey}->[3] = $Dependencies;
+ return 1;
+ }
+
+ return 0;
+}
+
+sub _GetNiceness($$)
+{
+ my ($NeededVMs, $VMKey) = @_;
+ return $NeededVMs->{$VMKey}->[0];
+}
+
+sub _CompareNeededVMs($$$)
+{
+ my ($NeededVMs, $VMKey1, $VMKey2) = @_;
+
+ my $Data1 = $NeededVMs->{$VMKey1};
+ my $Data2 = $NeededVMs->{$VMKey2};
+ return $Data1->[0] <=> $Data2->[0] || # Lower niceness jobs first
+ $Data2->[1] <=> $Data1->[1] || # Hot VMs first
+ $Data2->[2] <=> $Data1->[2]; # Needed by more tasks first
+}
+
+sub _HasMissingDependencies($$$)
+{
+ my ($Sched, $NeededVMs, $VMKey) = @_;
+
+ my $Data = $NeededVMs->{$VMKey};
+ return undef if (!$Data->[3]);
+
+ foreach my $DepVM (@{$Data->[3]})
{
+ return 1 if ($DepVM->Status !~ /^(?:reverting|sleeping|running)$/);
+ }
+ return undef;
+}
+
+my $NEXT_BASE = 1000;
+my $FUTURE_BASE = 2000;
+
+=pod
+=over 12
+
+=item C<_ScheduleTasks()>
+
+Runs the tasks on idle VMs, and builds a list of the VMs that will be needed
+next.
+
+=back
+=cut
+
+sub _ScheduleTasks($)
+{
+ my ($Sched) = @_;
+
+ # The set of VMs needed by the runnable, 'next step' and future tasks
+ my $NeededVMs = {};
+
+ # Process the jobs in decreasing priority order
+ my $JobRank;
+ my $Jobs = CreateJobs($Sched->{VMs});
+ $Jobs->AddFilter("Status", ["queued", "running"]);
+ foreach my $Job (sort CompareJobPriority @{$Jobs->GetItems()})
+ {
+ $JobRank++;
+
+ # The list of VMs that should be getting ready to run
+ # before we prepare the next step
+ my $PreviousVMs = [];
+
+ my $StepRank = 0;
my $Steps = $Job->Steps;
$Steps->AddFilter("Status", ["queued", "running"]);
- my @SortedSteps = sort { $a->No <=> $b->No } @{$Steps->GetItems()};
- if (@SortedSteps != 0)
+ foreach my $Step (sort { $a->No <=> $b->No } @{$Steps->GetItems()})
{
- my $Step = $SortedSteps[0];
- $Step->HandleStaging();
- my $PrepareNextStep;
my $Tasks = $Step->Tasks;
$Tasks->AddFilter("Status", ["queued"]);
- my @SortedTasks = sort { $a->No <=> $b->No } @{$Tasks->GetItems()};
- foreach my $Task (@SortedTasks)
+ $Sched->{queued} += $Tasks->GetItemsCount();
+
+ # StepRank 0 contains the runnable tasks, 1 the 'may soon be runnable'
+ # ones, and 2 and greater tasks we don't care about yet
+ next if ($StepRank >= 2);
+ if ($StepRank == 0)
+ {
+ $Step->HandleStaging() if ($Step->Status eq "queued");
+ $Sched->{runnable} += $Tasks->GetItemsCount();
+ }
+ elsif (!$PreviousVMs)
+ {
+ # The previous step is nowhere near done so skip this one for now
+ next;
+ }
+
+ my $StepVMs = [];
+ foreach my $Task (@{$Tasks->GetItems()})
{
my $VM = $Task->VM;
- my $VMKey = $VM->GetKey();
- next if (!$HostVMs->ItemExists($VMKey) || exists $VMsToRevert{$VMKey});
+ next if (!$VM->HasEnabledRole() or !$VM->HasEnabledStatus());
- my $VMStatus = $VM->Status;
- if ($VMStatus eq "idle")
+ if ($StepRank == 1)
{
+ # Passing $PreviousVMs ensures this VM will be reverted if and only
+ # if all of the previous step's tasks are about to run.
+ # See _HasMissingDependencies().
+ _AddNeededVM($NeededVMs, $VM, $NEXT_BASE + $JobRank, $PreviousVMs);
+ next;
+ }
+
+ if (!_AddNeededVM($NeededVMs, $VM, $JobRank))
+ {
+ # This VM is in $NeededVMs already which means it is already
+ # scheduled to be reverted for a task with a higher priority.
+ # So this task won't be run before a while and thus there is
+ # no point in preparing the next step.
+ $StepVMs = undef;
+ next;
+ }
+
+ # It's not worth preparing the next step for tasks that take so long
+ $StepVMs = undef if ($Task->Timeout > $BuildTimeout);
+
+ my $VMKey = $VM->GetKey();
+ if ($VM->Status eq "idle")
+ {
+ # Most of the time reverting a VM takes longer than running a task.
+ # So if a VM is ready (i.e. idle) we can start the first task we
+ # find for it, even if we could revert another VM to run a higher
+ # priority job.
# Even if we cannot start the task right away this VM is not a
# candidate for shutdown since it will be needed next.
- $IdleVMs{$VMKey} = 0;
+ delete $Sched->{lambvms}->{$VMKey};
- if ($RunningCount < $MaxActiveVMs and
- ($RevertingCount == 0 || $RevertingCount < $MaxRevertsWhileRunningVMs))
+ my $Host = _GetSchedHost($Sched, $VM);
+ if ($Host->{active} - $Host->{idle} < $Host->{MaxActiveVMs} and
+ ($Host->{reverting} == 0 or
+ $Host->{reverting} <= $Host->{MaxRevertsWhileRunningVMs}))
{
+ $Sched->{busyvms}->{$VMKey} = 1;
+ $VM->RecordStatus($Sched->{records}, join(" ", "running", $Job->Id, $Step->No, $Task->No));
my $ErrMessage = $Task->Run($Step);
- return $ErrMessage if (defined $ErrMessage);
- $VM->RecordStatus($Records, join(" ", "running", $Job->Id, $Step->No, $Task->No));
+ return ($ErrMessage, undef) if (defined $ErrMessage);
+
$Job->UpdateStatus();
- $IdleCount--;
- $RunningCount++;
- $PrepareNextStep = 1;
+ $Host->{idle}--;
+ $Host->{running}++;
}
}
- elsif ($VMStatus eq "sleeping" and $IdleVMs{$VMKey})
+ elsif ($VM->Status =~ /^(?:reverting|sleeping)$/)
{
- # It's not running jobs yet but soon will be
- # so it's not a candidate for shutdown or revert.
- $IdleVMs{$VMKey} = 0;
- $IdleCount--;
- $SleepingCount++;
- $PrepareNextStep = 1;
+ # The VM is not running jobs yet but soon will be so it is not a
+ # candidate for shutdown or sacrifices.
+ delete $Sched->{lambvms}->{$VMKey};
}
- elsif (($VMStatus eq "off" or $VMStatus eq "dirty") and
- !$VM->HasRunningChild())
+ elsif ($VM->Status ne "off" and !$Sched->{lambvms}->{$VMKey})
{
- $RevertNiceness++;
- $VMsToRevert{$VMKey} = $RevertNiceness;
- }
- }
- if ($PrepareNextStep && @SortedSteps >= 2)
- {
- # Build a list of VMs we will need next
- my $Step = $SortedSteps[1];
- $Tasks = $Step->Tasks;
- $Tasks->AddFilter("Status", ["queued"]);
- @SortedTasks = sort { $a->No <=> $b->No } @{$Tasks->GetItems()};
- foreach my $Task (@SortedTasks)
- {
- my $VM = $Task->VM;
- my $VMKey = $VM->GetKey();
- push @VMsNext, $VMKey;
- # If idle already this is not a candidate for shutdown
- $IdleVMs{$VMKey} = 0;
+ # We cannot use the VM because it is busy (running another task,
+ # offline, etc.). So it is too early to prepare the next step.
+ $StepVMs = undef;
}
+ push @$StepVMs, $VM if ($StepVMs);
}
+ $PreviousVMs = $StepVMs;
+ $StepRank++;
}
}
- # Figure out how many VMs we will actually be able to revert now and only
- # keep the highest priority ones.
- my @SortedVMsToRevert = sort { $VMsToRevert{$a} <=> $VMsToRevert{$b} } keys %VMsToRevert;
- my $MaxReverts = ($RunningCount > 0) ?
- $MaxRevertsWhileRunningVMs : $MaxRevertingVMs;
- my $ActiveCount = $IdleCount + $RunningCount + $RevertingCount + $SleepingCount + @DirtyVMs;
- # This is the number of VMs we would revert if idle and dirty VMs did not
- # stand in the way. And those that do will be shut down.
- my $RevertableCount = min(scalar(@SortedVMsToRevert),
- $MaxReverts - $RevertingCount,
- $MaxActiveVMs - ($ActiveCount - $IdleCount - @DirtyVMs));
- if ($RevertableCount < @SortedVMsToRevert)
+ # Finally add some VMs with a very low priority for future jobs.
+ foreach my $VM (@{$Sched->{VMs}->GetItems()})
{
- $RevertableCount = 0 if ($RevertableCount < 0);
- for (my $i = $RevertableCount; $i < @SortedVMsToRevert; $i++)
- {
- my $VMKey = $SortedVMsToRevert[$i];
- delete $VMsToRevert{$VMKey};
- }
- splice @SortedVMsToRevert, $RevertableCount;
+ next if (!$VM->HasEnabledRole() or !$VM->HasEnabledStatus());
+ my $VMKey = $VM->GetKey();
+ my $Niceness = $FUTURE_BASE + $Sched->{nicefuture}->{$VMKey};
+ _AddNeededVM($NeededVMs, $VM, $Niceness);
}
- # Power off all the VMs that we won't be reverting now so they don't waste
- # resources while waiting for their turn.
- foreach my $VMKey (@DirtyVMs)
- {
- next if (exists $VMsToRevert{$VMKey});
+ return (undef, $NeededVMs);
+}
- my $VM = $HostVMs->GetItem($VMKey);
- next if ($VM->Status ne "dirty" or $VM->HasRunningChild());
+=pod
+=over 12
- my $ErrMessage = $VM->RunPowerOff();
- return $ErrMessage if (defined $ErrMessage);
- $VM->RecordStatus($Records, "dirty poweroff");
- }
+=item C<_SacrificeVM()>
- # Power off some idle VMs we don't need immediately so we can revert more
- # of the VMs we need now.
- my $PlannedActiveCount = $ActiveCount - @DirtyVMs + @SortedVMsToRevert;
- if ($IdleCount > 0 && @SortedVMsToRevert > 0 &&
- $PlannedActiveCount > $MaxActiveVMs)
- {
- # Sort from least important to most important
- my @SortedIdleVMs = sort { $VMPriorities{$a} <=> $VMPriorities{$b} } keys %IdleVMs;
- foreach my $VMKey (@SortedIdleVMs)
- {
- my $VM = $HostVMs->GetItem($VMKey);
- next if (!$IdleVMs{$VMKey});
+Looks for and powers off a VM we don't need now in order to free resources
+for one we do need now.
- my $ErrMessage = $VM->RunPowerOff();
- return $ErrMessage if (defined $ErrMessage);
- $VM->RecordStatus($Records, "dirty poweroff");
- $PlannedActiveCount--;
- last if ($PlannedActiveCount <= $MaxActiveVMs);
- }
- # The scheduler will be run again when these VMs have been powered off and
- # then we will do the reverts. In the meantime don't change $ActiveCount.
- }
+This is a helper for _RevertVMs().
- # Revert the VMs that are blocking jobs
- foreach my $VMKey (@SortedVMsToRevert)
+=back
+=cut
+
+sub _SacrificeVM($$$)
+{
+ my ($Sched, $NeededVMs, $VM) =@_;
+ my $VMKey = $VM->GetKey();
+ my $Host = _GetSchedHost($Sched, $VM);
+
+ # Grab the lowest priority lamb and sacrifice it
+ my $ForFutureVM = (_GetNiceness($NeededVMs, $VMKey) >= $FUTURE_BASE);
+ my $NiceFuture = $Sched->{nicefuture};
+ my ($Victim, $VictimKey, $VictimStatusPrio);
+ foreach my $CandidateKey (keys %{$Sched->{lambvms}})
{
- last if ($RevertingCount == $MaxReverts);
+ my $Candidate = $Sched->{VMs}->GetItem($CandidateKey);
- my $VM = $HostVMs->GetItem($VMKey);
- next if ($VM->Status eq "off" and $ActiveCount >= $MaxActiveVMs);
+ # Check that the candidate is on the right host
+ my $CandidateHost = _GetSchedHost($Sched, $Candidate);
+ next if ($CandidateHost != $Host);
- delete $VMPriorities{$VMKey};
- my $ErrMessage = $VM->RunRevert();
- return $ErrMessage if (defined $ErrMessage);
+ # Don't sacrifice idle / sleeping VMs for future tasks
+ next if ($ForFutureVM and $Candidate->Status =~ /^(?:idle|sleeping)/);
- $RevertingCount++;
- $ActiveCount++ if ($VM->Status eq "off");
+ # Don't sacrifice more important VMs
+ next if (_CompareNeededVMs($NeededVMs, $CandidateKey, $VMKey) <= 0);
+
+ my $CandidateStatusPrio = $Candidate->Status eq "idle" ? 2 :
+ $Candidate->Status eq "sleeping" ? 1 :
+ 0; # Status eq dirty
+ if ($Victim)
+ {
+ my $Cmp = $VictimStatusPrio <=> $CandidateStatusPrio ||
+ $NiceFuture->{$CandidateKey} <=> $NiceFuture->{$VictimKey};
+ next if ($Cmp <= 0);
+ }
+
+ $Victim = $Candidate;
+ $VictimKey = $CandidateKey;
+ $VictimStatusPrio = $CandidateStatusPrio;
}
+ return undef if (!$Victim);
+
+ delete $Sched->{lambvms}->{$VictimKey};
+ $Sched->{busyvms}->{$VictimKey} = 1;
+ $Host->{$Victim->Status}--;
+ $Host->{dirty}++;
+ $Victim->RecordStatus($Sched->{records}, $Victim->Status eq "dirty" ? "dirty poweroff" : "dirty sacrifice");
+ $Victim->RunPowerOff();
+ return 1;
+}
- # Prepare some VMs for the next step of the current jobs
- foreach my $VMKey (@VMsNext)
+sub _RevertVMs($$)
+{
+ my ($Sched, $NeededVMs) = @_;
+
+ # Sort the VMs that tasks need by decreasing priority order and revert them
+ my @SortedNeededVMs = sort { _CompareNeededVMs($NeededVMs, $a, $b) } keys %{$NeededVMs};
+ foreach my $VMKey (@SortedNeededVMs)
{
- last if ($RevertingCount == $MaxReverts);
- last if ($ActiveCount >= $MaxActiveVMs);
+ my $VM = $Sched->{VMs}->GetItem($VMKey);
+ my $VMStatus = $VM->Status;
+ next if ($VMStatus eq "idle");
- my $VM = $HostVMs->GetItem($VMKey);
- next if ($VM->Status ne "off");
+ # Check if the host has reached its reverting VMs limit
+ my $Host = _GetSchedHost($Sched, $VM);
+ next if ($Host->{reverting} >= _GetMaxReverts($Host));
- my $ErrMessage = $VM->RunRevert();
- return $ErrMessage if (defined $ErrMessage);
- $RevertingCount++;
- $ActiveCount++;
- }
+ # Skip this VM if the previous step's tasks are not about to run yet
+ next if (_HasMissingDependencies($Sched, $NeededVMs, $VMKey));
+ next if (!_CanScheduleOnVM($Sched, $VM));
- # Finally, if we are otherwise idle, prepare some VMs for future jobs
- if ($ActiveCount == $IdleCount && $ActiveCount < $MaxVMsWhenIdle)
- {
- # Sort from most important to least important
- my @SortedVMs = sort { $VMPriorities{$b} <=> $VMPriorities{$a} } keys %VMPriorities;
- foreach my $VMKey (@SortedVMs)
+ my $NeedsSacrifice;
+ if (_GetNiceness($NeededVMs, $VMKey) >= $FUTURE_BASE)
{
- last if ($RevertingCount == $MaxReverts);
- last if ($ActiveCount >= $MaxVMsWhenIdle);
-
- my $VM = $HostVMs->GetItem($VMKey);
- next if ($VM->Status ne "off");
+ if (!exists $Host->{isidle})
+ {
+ # Only start preparing VMs for future jobs on a host which is idle.
+ # FIXME As a proxy we currently check that the host only has idle VMs.
+ # This is a bad proxy because:
+ # - The host could still have pending tasks for a 'next step'. Once
+ # those get closer to running, preparing those would be better than
+ # preparing future VMs.
+ # - Checking there are no queued tasks on that host would be better
+ # but this information is not available on a per-host basis.
+ # - Also the number of queued tasks includes tasks scheduled to run
+ # on maintenance and retired/deleted VMs. Any such task would prevent
+ # preparing future VMs for no good reason.
+ # - It forces the host to go through an extra poweroff during which we
+ # lose track of which VM is 'hot'.
+ # - However on startup this helps ensure that we are not prevented
+ # from preparing the best VM (e.g. build) just because it is still
+ # being checked (i.e. marked dirty).
+ $Host->{isidle} = ($Host->{active} == $Host->{idle});
+ }
+ if (!$Host->{isidle} or $Host->{MaxVMsWhenIdle} == 0)
+ {
+ # The TestBot is busy or does not prepare VMs when idle
+ next;
+ }
+ # To not exceed the limit we must take into account VMs that are not yet
+ # idle but will soon be.
+ my $FutureIdle = $Host->{idle} + $Host->{reverting} + $Host->{sleeping} + ($VMStatus eq "off" ? 1 : 0);
+ $NeedsSacrifice = ($FutureIdle > $Host->{MaxVMsWhenIdle});
+ }
+ else
+ {
+ my $FutureActive = $Host->{active} + ($VMStatus eq "off" ? 1 : 0);
+ $NeedsSacrifice = ($FutureActive > $Host->{MaxActiveVMs});
+ }
+ if ($NeedsSacrifice)
+ {
+ # Find an active VM to sacrifice so we can revert this VM in the next
+ # scheduler round
+ last if (!_SacrificeVM($Sched, $NeededVMs, $VM));
+ delete $Sched->{lambvms}->{$VMKey};
+ # The $Host counters must account for the coming revert. This means
+ # active is unchanged: -1 for the sacrificed VM and +1 for the revert.
+ $Host->{reverting}++;
+ }
+ else
+ {
+ delete $Sched->{lambvms}->{$VMKey};
+ $Sched->{busyvms}->{$VMKey} = 1;
my $ErrMessage = $VM->RunRevert();
return $ErrMessage if (defined $ErrMessage);
- $RevertingCount++;
- $ActiveCount++;
+ $Host->{active}++ if ($VMStatus eq "off");
+ $Host->{reverting}++;
}
}
+ return undef;
+}
+sub _PowerOffDirtyVMs($)
+{
+ my ($Sched) = @_;
+
+ # Power off any still dirty VM
+ foreach my $VMKey (keys %{$Sched->{lambvms}})
+ {
+ my $VM = $Sched->{VMs}->GetItem($VMKey);
+ next if ($VM->Status ne "dirty");
+
+ $VM->RecordStatus($Sched->{records}, "dirty poweroff");
+ my $ErrMessage = $VM->RunPowerOff();
+ return $ErrMessage if (defined $ErrMessage);
+ }
return undef;
}
@@ -744,106 +1118,92 @@ my $_LastTaskCounts = "";
=item C<ScheduleJobs()>
-Goes through the WineTestBot hosts and schedules the Job tasks on each of
-them using WineTestBot::Jobs::ScheduleOnHost().
+Goes through the pending Jobs to run their queued Tasks. This implies preparing
+the VMs while staying within the VM hosts resource limits. In particular this
+means taking the following constraints into account:
+
+=over
+
+=item *
+
+Jobs should be run in decreasing order of priority.
+
+=item *
+
+A Job's Steps must be run in sequential order.
+
+=item *
+
+A Step's tasks can be run in parallel but only one task can be running in a VM
+at a given time. Also a VM must be prepared before it can run its task, see the
+VM Statuses.
+
+=item *
+
+The number of active VMs on the host must be kept under $MaxActiveVMs. Any
+VM using resources counts as an active VM, including those that are being
+reverted. This limit is meant to ensure the VM host will have enough memory,
+CPU or I/O resources for all the active VMs. Also note that this limit must be
+respected even if there is more than one hypervisor running on the host.
+
+=item *
+
+The number of VMs being reverted on the host at a given time must be kept under
+$MaxRevertingVMs, or $MaxRevertsWhileRunningVMs if some VMs are currently
+running tests. This may be set to 1 in case the hypervisor gets confused when
+reverting too many VMs at once.
+
+=item *
+
+Once there are no jobs to run anymore the scheduler can prepare up to
+$MaxVMsWhenIdle VMs (or $MaxActiveVMs if not set) for future jobs.
+This can be set to 0 to minimize the TestBot resource usage when idle.
+This can also be set to a value greater than $MaxActiveVMs. Then only
+$MaxActiveVMs tasks will be run simultaneously but the extra idle VMs will be
+kept on standby so they are ready when their turn comes.
+
+=back
=back
=cut
sub ScheduleJobs()
{
- my $RecordGroups = CreateRecordGroups();
- my $RecordGroup = $RecordGroups->Add();
- my $Records = $RecordGroup->Records;
- # Save the new RecordGroup now so its Id is lower than those of the groups
- # created by the scripts called from the scheduler.
- $RecordGroups->Save();
+ my ($ErrMessage, $Sched) = _CheckAndClassifyVMs();
+ return $ErrMessage if ($ErrMessage);
- my $Jobs = CreateJobs();
- $Jobs->AddFilter("Status", ["queued", "running"]);
- my @SortedJobs = sort CompareJobPriority @{$Jobs->GetItems()};
- # Note that even if there are no jobs to schedule
- # we should check if there are VMs to revert
+ my $NeededVMs;
+ ($ErrMessage, $NeededVMs) = _ScheduleTasks($Sched);
+ return $ErrMessage if ($ErrMessage);
- # Count the runnable and queued tasks for the record
- my ($RunnableTasks, $QueuedTasks) = (0, 0);
- foreach my $Job (@SortedJobs)
- {
- my $Steps = $Job->Steps;
- $Steps->AddFilter("Status", ["queued", "running"]);
- my @SortedSteps = sort { $a->No <=> $b->No } @{$Steps->GetItems()};
- next if (!@SortedSteps);
+ $ErrMessage = _RevertVMs($Sched, $NeededVMs);
+ return $ErrMessage if ($ErrMessage);
- my $Tasks = $SortedSteps[0]->Tasks;
- $Tasks->AddFilter("Status", ["queued"]);
- $RunnableTasks += @{$Tasks->GetItems()};
-
- foreach my $Step (@SortedSteps)
- {
- my $Tasks = $Step->Tasks;
- $Tasks->AddFilter("Status", ["queued"]);
- $QueuedTasks += scalar(@{$Tasks->GetItems()});
- }
- }
-
- my %Hosts;
- my $VMs = CreateVMs($Jobs);
- $VMs->FilterEnabledRole();
- foreach my $VM (@{$VMs->GetItems()})
- {
- my $Host = $VM->GetHost();
- $Hosts{$Host}->{$VM->VirtURI} = 1;
- }
-
- my @ErrMessages;
- foreach my $Host (keys %Hosts)
- {
- my @HostHypervisors = keys %{$Hosts{$Host}};
- my $HostErrMessage = ScheduleOnHost($Jobs, \@SortedJobs, \@HostHypervisors, $Records);
- push @ErrMessages, $HostErrMessage if (defined $HostErrMessage);
- }
+ $ErrMessage = _PowerOffDirtyVMs($Sched);
+ return $ErrMessage if ($ErrMessage);
# Note that any VM Status or Role change will trigger ScheduleJobs() so this
- # records all VM state changes.
- $VMs = CreateVMs();
- map { $_->RecordStatus($Records) } (@{$VMs->GetItems()});
- if (@{$Records->GetItems()})
+ # records all not yet recorded VM state changes, even those not initiated by
+ # the scheduler.
+ map { $_->RecordStatus($Sched->{records}) } @{$Sched->{VMs}->GetItems()};
+
+ if (@{$Sched->{records}->GetItems()})
{
# FIXME Add the number of tasks scheduled to run on a maintenance, retired
# or deleted VM...
- my $TaskCounts = "$RunnableTasks $QueuedTasks 0";
+ my $TaskCounts = "$Sched->{runnable} $Sched->{queued} 0";
if ($TaskCounts ne $_LastTaskCounts)
{
- $Records->AddRecord('tasks', 'counters', $TaskCounts);
+ $Sched->{records}->AddRecord('tasks', 'counters', $TaskCounts);
$_LastTaskCounts = $TaskCounts;
}
- $RecordGroups->Save();
+ $Sched->{recordgroups}->Save();
}
else
{
- $RecordGroups->DeleteItem($RecordGroup);
+ $Sched->{recordgroups}->DeleteItem($Sched->{recordgroup});
}
- return @ErrMessages ? join("\n", @ErrMessages) : undef;
-}
-
-=pod
-=over 12
-
-=item C<CheckJobs()>
-
-Goes through the list of Jobs and updates their status. As a side-effect this
-detects failed builds, dead child processes, etc.
-
-=back
-=cut
-
-sub CheckJobs()
-{
- my $Jobs = CreateJobs();
- $Jobs->AddFilter("Status", ["queued", "running"]);
- map { $_->UpdateStatus(); } @{$Jobs->GetItems()};
-
return undef;
}
--
2.16.1
1
0
[PATCH 5/5] ddraw: Compare with the correct view in ddraw_surface_delete_attached_surface().
by Henri Verbeet 18 Feb '18
by Henri Verbeet 18 Feb '18
18 Feb '18
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/ddraw/surface.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c
index 739e68f..30276b4 100644
--- a/dlls/ddraw/surface.c
+++ b/dlls/ddraw/surface.c
@@ -2069,7 +2069,7 @@ static HRESULT ddraw_surface_delete_attached_surface(struct ddraw_surface *surfa
* particular, modify the QueryInterface() pointer in the surface vtbl
* but don't cleanup properly after the relevant dll is unloaded. */
if (attachment->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER
- && wined3d_device_get_depth_stencil_view(surface->ddraw->wined3d_device) == surface->wined3d_rtv)
+ && wined3d_device_get_depth_stencil_view(surface->ddraw->wined3d_device) == attachment->wined3d_rtv)
wined3d_device_set_depth_stencil_view(surface->ddraw->wined3d_device, NULL);
wined3d_mutex_unlock();
--
2.1.4
1
0
[PATCH 2/5] wined3d: Split WINED3D_RESOURCE_ACCESS_MAP into WINED3D_RESOURCE_ACCESS_MAP_R and WINED3D_RESOURCE_ACCESS_MAP_W.
by Henri Verbeet 18 Feb '18
by Henri Verbeet 18 Feb '18
18 Feb '18
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/d3d10core/tests/device.c | 12 ++++--------
dlls/d3d11/tests/d3d11.c | 6 ++----
dlls/d3d11/utils.c | 12 ++++++------
dlls/d3d8/buffer.c | 6 ++++--
dlls/d3d8/d3d8_private.h | 7 ++++---
dlls/d3d8/device.c | 7 ++++---
dlls/d3d8/texture.c | 6 ++++--
dlls/d3d9/buffer.c | 6 ++++--
dlls/d3d9/d3d9_private.h | 7 ++++---
dlls/d3d9/device.c | 7 ++++---
dlls/d3d9/texture.c | 6 ++++--
dlls/ddraw/device.c | 4 ++--
dlls/ddraw/executebuffer.c | 7 ++++---
dlls/ddraw/surface.c | 7 ++++---
dlls/ddraw/vertexbuffer.c | 4 ++--
dlls/wined3d/resource.c | 10 ++++++++--
dlls/wined3d/surface.c | 2 +-
dlls/wined3d/texture.c | 2 +-
dlls/wined3d/utils.c | 3 ++-
include/wine/wined3d.h | 3 ++-
20 files changed, 70 insertions(+), 54 deletions(-)
diff --git a/dlls/d3d10core/tests/device.c b/dlls/d3d10core/tests/device.c
index 6607059..0903ab1 100644
--- a/dlls/d3d10core/tests/device.c
+++ b/dlls/d3d10core/tests/device.c
@@ -8199,28 +8199,26 @@ static void check_buffer_cpu_access_(unsigned int line, ID3D10Buffer *buffer,
expected_hr = cpu_read ? S_OK : E_INVALIDARG;
hr = ID3D10Buffer_Map(buffer, D3D10_MAP_READ, 0, &data);
- todo_wine_if(expected_hr != S_OK && cpu_access)
ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x for READ.\n", hr);
if (SUCCEEDED(hr))
ID3D10Buffer_Unmap(buffer);
expected_hr = !dynamic && cpu_write ? S_OK : E_INVALIDARG;
hr = ID3D10Buffer_Map(buffer, D3D10_MAP_WRITE, 0, &data);
- todo_wine_if(expected_hr != S_OK && cpu_access)
+ todo_wine_if(dynamic && cpu_write)
ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x for WRITE.\n", hr);
if (SUCCEEDED(hr))
ID3D10Buffer_Unmap(buffer);
expected_hr = cpu_read && cpu_write ? S_OK : E_INVALIDARG;
hr = ID3D10Buffer_Map(buffer, D3D10_MAP_READ_WRITE, 0, &data);
- todo_wine_if(expected_hr != S_OK && cpu_access)
ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x for READ_WRITE.\n", hr);
if (SUCCEEDED(hr))
ID3D10Buffer_Unmap(buffer);
expected_hr = dynamic ? S_OK : E_INVALIDARG;
hr = ID3D10Buffer_Map(buffer, D3D10_MAP_WRITE_DISCARD, 0, &data);
- todo_wine_if(expected_hr != S_OK && cpu_access)
+ todo_wine_if(!dynamic && cpu_write)
ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x for WRITE_DISCARD.\n", hr);
if (SUCCEEDED(hr))
ID3D10Buffer_Unmap(buffer);
@@ -8254,28 +8252,26 @@ static void check_texture_cpu_access_(unsigned int line, ID3D10Texture2D *textur
expected_hr = cpu_read ? S_OK : E_INVALIDARG;
hr = ID3D10Texture2D_Map(texture, 0, D3D10_MAP_READ, 0, &map_desc);
- todo_wine_if(expected_hr != S_OK && cpu_access)
ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x for READ.\n", hr);
if (SUCCEEDED(hr))
ID3D10Texture2D_Unmap(texture, 0);
expected_hr = !dynamic && cpu_write ? S_OK : E_INVALIDARG;
hr = ID3D10Texture2D_Map(texture, 0, D3D10_MAP_WRITE, 0, &map_desc);
- todo_wine_if(expected_hr != S_OK && cpu_access)
+ todo_wine_if(dynamic && cpu_write)
ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x for WRITE.\n", hr);
if (SUCCEEDED(hr))
ID3D10Texture2D_Unmap(texture, 0);
expected_hr = cpu_read && cpu_write ? S_OK : E_INVALIDARG;
hr = ID3D10Texture2D_Map(texture, 0, D3D10_MAP_READ_WRITE, 0, &map_desc);
- todo_wine_if(expected_hr != S_OK && cpu_access)
ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x for READ_WRITE.\n", hr);
if (SUCCEEDED(hr))
ID3D10Texture2D_Unmap(texture, 0);
expected_hr = dynamic ? S_OK : E_INVALIDARG;
hr = ID3D10Texture2D_Map(texture, 0, D3D10_MAP_WRITE_DISCARD, 0, &map_desc);
- todo_wine_if(expected_hr != S_OK && cpu_access)
+ todo_wine_if(!dynamic && cpu_write)
ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x for WRITE_DISCARD.\n", hr);
if (SUCCEEDED(hr))
ID3D10Texture2D_Unmap(texture, 0);
diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c
index af8fc7b..35551d0 100644
--- a/dlls/d3d11/tests/d3d11.c
+++ b/dlls/d3d11/tests/d3d11.c
@@ -11029,7 +11029,6 @@ static void check_resource_cpu_access_(unsigned int line, ID3D11DeviceContext *c
expected_hr = cpu_read ? S_OK : E_INVALIDARG;
hr = ID3D11DeviceContext_Map(context, resource, 0, D3D11_MAP_READ, 0, &map_desc);
- todo_wine_if(expected_hr != S_OK && cpu_access)
ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x for READ.\n", hr);
if (SUCCEEDED(hr))
ID3D11DeviceContext_Unmap(context, resource, 0);
@@ -11037,21 +11036,20 @@ static void check_resource_cpu_access_(unsigned int line, ID3D11DeviceContext *c
/* WRITE_DISCARD and WRITE_NO_OVERWRITE are the only allowed options for dynamic resources. */
expected_hr = !dynamic && cpu_write ? S_OK : E_INVALIDARG;
hr = ID3D11DeviceContext_Map(context, resource, 0, D3D11_MAP_WRITE, 0, &map_desc);
- todo_wine_if(expected_hr != S_OK && cpu_access)
+ todo_wine_if(dynamic && cpu_write)
ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x for WRITE.\n", hr);
if (SUCCEEDED(hr))
ID3D11DeviceContext_Unmap(context, resource, 0);
expected_hr = cpu_read && cpu_write ? S_OK : E_INVALIDARG;
hr = ID3D11DeviceContext_Map(context, resource, 0, D3D11_MAP_READ_WRITE, 0, &map_desc);
- todo_wine_if(expected_hr != S_OK && cpu_access)
ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x for READ_WRITE.\n", hr);
if (SUCCEEDED(hr))
ID3D11DeviceContext_Unmap(context, resource, 0);
expected_hr = dynamic ? S_OK : E_INVALIDARG;
hr = ID3D11DeviceContext_Map(context, resource, 0, D3D11_MAP_WRITE_DISCARD, 0, &map_desc);
- todo_wine_if(expected_hr != S_OK && cpu_access)
+ todo_wine_if(!dynamic && cpu_write)
ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x for WRITE_DISCARD.\n", hr);
if (SUCCEEDED(hr))
ID3D11DeviceContext_Unmap(context, resource, 0);
diff --git a/dlls/d3d11/utils.c b/dlls/d3d11/utils.c
index 5c6add7..cd226b2 100644
--- a/dlls/d3d11/utils.c
+++ b/dlls/d3d11/utils.c
@@ -801,12 +801,12 @@ unsigned int wined3d_access_from_d3d11(D3D11_USAGE usage, UINT cpu_access)
unsigned int access;
access = usage == D3D11_USAGE_STAGING ? WINED3D_RESOURCE_ACCESS_CPU : WINED3D_RESOURCE_ACCESS_GPU;
- if (cpu_access)
- {
- if (~cpu_access & (D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ))
- FIXME("Ignoring CPU access flags %#x.\n", cpu_access);
- access |= WINED3D_RESOURCE_ACCESS_MAP;
- }
+ if (cpu_access & D3D11_CPU_ACCESS_WRITE)
+ access |= WINED3D_RESOURCE_ACCESS_MAP_W;
+ if (cpu_access & D3D11_CPU_ACCESS_READ)
+ access |= WINED3D_RESOURCE_ACCESS_MAP_R;
+ if (cpu_access &= ~(D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ))
+ FIXME("Unhandled CPU access flags %#x.\n", cpu_access);
return access;
}
diff --git a/dlls/d3d8/buffer.c b/dlls/d3d8/buffer.c
index d4d73ad..fb6b7bc 100644
--- a/dlls/d3d8/buffer.c
+++ b/dlls/d3d8/buffer.c
@@ -289,7 +289,8 @@ HRESULT vertexbuffer_init(struct d3d8_vertexbuffer *buffer, struct d3d8_device *
desc.byte_width = size;
desc.usage = usage & WINED3DUSAGE_MASK;
desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER;
- desc.access = wined3daccess_from_d3dpool(pool, usage) | WINED3D_RESOURCE_ACCESS_MAP;
+ desc.access = wined3daccess_from_d3dpool(pool, usage)
+ | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
desc.misc_flags = 0;
desc.structure_byte_stride = 0;
@@ -577,7 +578,8 @@ HRESULT indexbuffer_init(struct d3d8_indexbuffer *buffer, struct d3d8_device *de
if (pool == D3DPOOL_SCRATCH)
desc.usage |= WINED3DUSAGE_SCRATCH;
desc.bind_flags = WINED3D_BIND_INDEX_BUFFER;
- desc.access = wined3daccess_from_d3dpool(pool, usage) | WINED3D_RESOURCE_ACCESS_MAP;
+ desc.access = wined3daccess_from_d3dpool(pool, usage)
+ | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
desc.misc_flags = 0;
desc.structure_byte_stride = 0;
diff --git a/dlls/d3d8/d3d8_private.h b/dlls/d3d8/d3d8_private.h
index ecde77a..cba5dd6 100644
--- a/dlls/d3d8/d3d8_private.h
+++ b/dlls/d3d8/d3d8_private.h
@@ -304,13 +304,14 @@ static inline unsigned int wined3daccess_from_d3dpool(D3DPOOL pool, unsigned int
{
case D3DPOOL_DEFAULT:
if (usage & D3DUSAGE_DYNAMIC)
- return WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP;
+ return WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
return WINED3D_RESOURCE_ACCESS_GPU;
case D3DPOOL_MANAGED:
- return WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_CPU | WINED3D_RESOURCE_ACCESS_MAP;
+ return WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_CPU
+ | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
case D3DPOOL_SYSTEMMEM:
case D3DPOOL_SCRATCH:
- return WINED3D_RESOURCE_ACCESS_CPU | WINED3D_RESOURCE_ACCESS_MAP;
+ return WINED3D_RESOURCE_ACCESS_CPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
default:
return 0;
}
diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c
index 090d196..5daf6f4 100644
--- a/dlls/d3d8/device.c
+++ b/dlls/d3d8/device.c
@@ -1077,7 +1077,8 @@ static HRESULT d3d8_device_create_surface(struct d3d8_device *device, UINT width
desc.usage = usage & WINED3DUSAGE_MASK;
if (pool == D3DPOOL_SCRATCH)
desc.usage |= WINED3DUSAGE_SCRATCH;
- desc.access = wined3daccess_from_d3dpool(pool, usage) | WINED3D_RESOURCE_ACCESS_MAP;
+ desc.access = wined3daccess_from_d3dpool(pool, usage)
+ | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
desc.width = width;
desc.height = height;
desc.depth = 1;
@@ -2170,7 +2171,7 @@ static HRESULT d3d8_device_prepare_vertex_buffer(struct d3d8_device *device, UIN
desc.byte_width = size;
desc.usage = WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY;
desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER;
- desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP;
+ desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
desc.misc_flags = 0;
desc.structure_byte_stride = 0;
@@ -2265,7 +2266,7 @@ static HRESULT d3d8_device_prepare_index_buffer(struct d3d8_device *device, UINT
desc.byte_width = size;
desc.usage = WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_STATICDECL;
desc.bind_flags = WINED3D_BIND_INDEX_BUFFER;
- desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP;
+ desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
desc.misc_flags = 0;
desc.structure_byte_stride = 0;
diff --git a/dlls/d3d8/texture.c b/dlls/d3d8/texture.c
index d81c3bc..f7ccdc7 100644
--- a/dlls/d3d8/texture.c
+++ b/dlls/d3d8/texture.c
@@ -1110,7 +1110,8 @@ HRESULT texture_init(struct d3d8_texture *texture, struct d3d8_device *device,
desc.usage |= WINED3DUSAGE_TEXTURE;
if (pool == D3DPOOL_SCRATCH)
desc.usage |= WINED3DUSAGE_SCRATCH;
- desc.access = wined3daccess_from_d3dpool(pool, usage) | WINED3D_RESOURCE_ACCESS_MAP;
+ desc.access = wined3daccess_from_d3dpool(pool, usage)
+ | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
desc.width = width;
desc.height = height;
desc.depth = 1;
@@ -1157,7 +1158,8 @@ HRESULT cubetexture_init(struct d3d8_texture *texture, struct d3d8_device *devic
desc.usage |= WINED3DUSAGE_LEGACY_CUBEMAP | WINED3DUSAGE_TEXTURE;
if (pool == D3DPOOL_SCRATCH)
desc.usage |= WINED3DUSAGE_SCRATCH;
- desc.access = wined3daccess_from_d3dpool(pool, usage) | WINED3D_RESOURCE_ACCESS_MAP;
+ desc.access = wined3daccess_from_d3dpool(pool, usage)
+ | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
desc.width = edge_length;
desc.height = edge_length;
desc.depth = 1;
diff --git a/dlls/d3d9/buffer.c b/dlls/d3d9/buffer.c
index 04c87c8..36a6ae3 100644
--- a/dlls/d3d9/buffer.c
+++ b/dlls/d3d9/buffer.c
@@ -290,7 +290,8 @@ HRESULT vertexbuffer_init(struct d3d9_vertexbuffer *buffer, struct d3d9_device *
desc.byte_width = size;
desc.usage = usage & WINED3DUSAGE_MASK;
desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER;
- desc.access = wined3daccess_from_d3dpool(pool, usage) | WINED3D_RESOURCE_ACCESS_MAP;
+ desc.access = wined3daccess_from_d3dpool(pool, usage)
+ | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
desc.misc_flags = 0;
desc.structure_byte_stride = 0;
@@ -576,7 +577,8 @@ HRESULT indexbuffer_init(struct d3d9_indexbuffer *buffer, struct d3d9_device *de
if (pool == D3DPOOL_SCRATCH)
desc.usage |= WINED3DUSAGE_SCRATCH;
desc.bind_flags = WINED3D_BIND_INDEX_BUFFER;
- desc.access = wined3daccess_from_d3dpool(pool, usage) | WINED3D_RESOURCE_ACCESS_MAP;
+ desc.access = wined3daccess_from_d3dpool(pool, usage)
+ | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
desc.misc_flags = 0;
desc.structure_byte_stride = 0;
diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h
index 92bbacd..ee385d9 100644
--- a/dlls/d3d9/d3d9_private.h
+++ b/dlls/d3d9/d3d9_private.h
@@ -321,13 +321,14 @@ static inline unsigned int wined3daccess_from_d3dpool(D3DPOOL pool, unsigned int
{
case D3DPOOL_DEFAULT:
if (usage & D3DUSAGE_DYNAMIC)
- return WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP;
+ return WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
return WINED3D_RESOURCE_ACCESS_GPU;
case D3DPOOL_MANAGED:
- return WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_CPU | WINED3D_RESOURCE_ACCESS_MAP;
+ return WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_CPU
+ | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
case D3DPOOL_SYSTEMMEM:
case D3DPOOL_SCRATCH:
- return WINED3D_RESOURCE_ACCESS_CPU | WINED3D_RESOURCE_ACCESS_MAP;
+ return WINED3D_RESOURCE_ACCESS_CPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
default:
return 0;
}
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c
index b278d6d..5f88278 100644
--- a/dlls/d3d9/device.c
+++ b/dlls/d3d9/device.c
@@ -1348,7 +1348,8 @@ static HRESULT d3d9_device_create_surface(struct d3d9_device *device, UINT width
desc.usage = usage & WINED3DUSAGE_MASK;
if (pool == D3DPOOL_SCRATCH)
desc.usage |= WINED3DUSAGE_SCRATCH;
- desc.access = wined3daccess_from_d3dpool(pool, usage) | WINED3D_RESOURCE_ACCESS_MAP;
+ desc.access = wined3daccess_from_d3dpool(pool, usage)
+ | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
desc.width = width;
desc.height = height;
desc.depth = 1;
@@ -2675,7 +2676,7 @@ static HRESULT d3d9_device_prepare_vertex_buffer(struct d3d9_device *device, UIN
desc.byte_width = size;
desc.usage = WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY;
desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER;
- desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP;
+ desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
desc.misc_flags = 0;
desc.structure_byte_stride = 0;
@@ -2780,7 +2781,7 @@ static HRESULT d3d9_device_prepare_index_buffer(struct d3d9_device *device, UINT
desc.byte_width = size;
desc.usage = WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_STATICDECL;
desc.bind_flags = WINED3D_BIND_INDEX_BUFFER;
- desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP;
+ desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
desc.misc_flags = 0;
desc.structure_byte_stride = 0;
diff --git a/dlls/d3d9/texture.c b/dlls/d3d9/texture.c
index ec00776..e7efe73 100644
--- a/dlls/d3d9/texture.c
+++ b/dlls/d3d9/texture.c
@@ -1314,7 +1314,8 @@ HRESULT texture_init(struct d3d9_texture *texture, struct d3d9_device *device,
desc.usage |= WINED3DUSAGE_TEXTURE;
if (pool == D3DPOOL_SCRATCH)
desc.usage |= WINED3DUSAGE_SCRATCH;
- desc.access = wined3daccess_from_d3dpool(pool, usage) | WINED3D_RESOURCE_ACCESS_MAP;
+ desc.access = wined3daccess_from_d3dpool(pool, usage)
+ | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
desc.width = width;
desc.height = height;
desc.depth = 1;
@@ -1385,7 +1386,8 @@ HRESULT cubetexture_init(struct d3d9_texture *texture, struct d3d9_device *devic
desc.usage |= WINED3DUSAGE_LEGACY_CUBEMAP | WINED3DUSAGE_TEXTURE;
if (pool == D3DPOOL_SCRATCH)
desc.usage |= WINED3DUSAGE_SCRATCH;
- desc.access = wined3daccess_from_d3dpool(pool, usage) | WINED3D_RESOURCE_ACCESS_MAP;
+ desc.access = wined3daccess_from_d3dpool(pool, usage)
+ | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
desc.width = edge_length;
desc.height = edge_length;
desc.depth = 1;
diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c
index 463d036..c2d87dd 100644
--- a/dlls/ddraw/device.c
+++ b/dlls/ddraw/device.c
@@ -3471,7 +3471,7 @@ static HRESULT d3d_device_prepare_vertex_buffer(struct d3d_device *device, UINT
desc.byte_width = size;
desc.usage = WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY;
desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER;
- desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP;
+ desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
desc.misc_flags = 0;
desc.structure_byte_stride = 0;
@@ -3663,7 +3663,7 @@ static HRESULT d3d_device_prepare_index_buffer(struct d3d_device *device, UINT m
desc.byte_width = size;
desc.usage = WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_STATICDECL;
desc.bind_flags = WINED3D_BIND_INDEX_BUFFER;
- desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP;
+ desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
desc.misc_flags = 0;
desc.structure_byte_stride = 0;
diff --git a/dlls/ddraw/executebuffer.c b/dlls/ddraw/executebuffer.c
index 19ef9c0..497287e 100644
--- a/dlls/ddraw/executebuffer.c
+++ b/dlls/ddraw/executebuffer.c
@@ -131,7 +131,8 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
desc.byte_width = new_size * sizeof(*indices);
desc.usage = WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_STATICDECL;
desc.bind_flags = WINED3D_BIND_INDEX_BUFFER;
- desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP;
+ desc.access = WINED3D_RESOURCE_ACCESS_GPU
+ | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
desc.misc_flags = 0;
desc.structure_byte_stride = 0;
@@ -621,7 +622,7 @@ static HRESULT WINAPI d3d_execute_buffer_SetExecuteData(IDirect3DExecuteBuffer *
desc.byte_width = new_size * sizeof(D3DVERTEX);
desc.usage = 0;
desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER;
- desc.access = WINED3D_RESOURCE_ACCESS_CPU | WINED3D_RESOURCE_ACCESS_MAP;
+ desc.access = WINED3D_RESOURCE_ACCESS_CPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
desc.misc_flags = 0;
desc.structure_byte_stride = 0;
@@ -631,7 +632,7 @@ static HRESULT WINAPI d3d_execute_buffer_SetExecuteData(IDirect3DExecuteBuffer *
desc.byte_width = new_size * sizeof(D3DTLVERTEX);
desc.usage = WINED3DUSAGE_STATICDECL;
- desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP;
+ desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
if (FAILED(hr = wined3d_buffer_create(buffer->d3ddev->wined3d_device, &desc,
NULL, NULL, &ddraw_null_wined3d_parent_ops, &dst_buffer)))
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c
index 8280990..739e68f 100644
--- a/dlls/ddraw/surface.c
+++ b/dlls/ddraw/surface.c
@@ -6012,7 +6012,7 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_
wined3d_desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
wined3d_desc.multisample_quality = 0;
wined3d_desc.usage = 0;
- wined3d_desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP;
+ wined3d_desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
wined3d_desc.width = desc->dwWidth;
wined3d_desc.height = desc->dwHeight;
wined3d_desc.depth = 1;
@@ -6101,7 +6101,8 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_
if (desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
{
- wined3d_desc.access = WINED3D_RESOURCE_ACCESS_CPU | WINED3D_RESOURCE_ACCESS_MAP;
+ wined3d_desc.access = WINED3D_RESOURCE_ACCESS_CPU
+ | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
}
else
{
@@ -6115,7 +6116,7 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_
if (desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))
{
wined3d_desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_CPU
- | WINED3D_RESOURCE_ACCESS_MAP;
+ | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
/* Managed textures have the system memory flag set. */
desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
}
diff --git a/dlls/ddraw/vertexbuffer.c b/dlls/ddraw/vertexbuffer.c
index b661e73..3ad8f7e 100644
--- a/dlls/ddraw/vertexbuffer.c
+++ b/dlls/ddraw/vertexbuffer.c
@@ -125,9 +125,9 @@ static HRESULT d3d_vertex_buffer_create_wined3d_buffer(struct d3d_vertex_buffer
desc.usage |= WINED3DUSAGE_DYNAMIC;
desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER;
if (buffer->Caps & D3DVBCAPS_SYSTEMMEMORY)
- desc.access = WINED3D_RESOURCE_ACCESS_CPU | WINED3D_RESOURCE_ACCESS_MAP;
+ desc.access = WINED3D_RESOURCE_ACCESS_CPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
else
- desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP;
+ desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
desc.misc_flags = 0;
desc.structure_byte_stride = 0;
diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c
index ac36183..97f7aec 100644
--- a/dlls/wined3d/resource.c
+++ b/dlls/wined3d/resource.c
@@ -349,9 +349,15 @@ HRESULT CDECL wined3d_resource_map(struct wined3d_resource *resource, unsigned i
return E_INVALIDARG;
}
- if (!(resource->access & WINED3D_RESOURCE_ACCESS_MAP))
+ if ((flags & WINED3D_MAP_READ) && !(resource->access & WINED3D_RESOURCE_ACCESS_MAP_R))
{
- WARN("Resource is not mappable.\n");
+ WARN("Resource does not have MAP_R access.\n");
+ return E_INVALIDARG;
+ }
+
+ if ((flags & WINED3D_MAP_WRITE) && !(resource->access & WINED3D_RESOURCE_ACCESS_MAP_W))
+ {
+ WARN("Resource does not have MAP_W access.\n");
return E_INVALIDARG;
}
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 7cf9c21..c3fabef 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -1330,7 +1330,7 @@ static struct wined3d_texture *surface_convert_format(struct wined3d_texture *sr
desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
desc.multisample_quality = 0;
desc.usage = WINED3DUSAGE_SCRATCH | WINED3DUSAGE_PRIVATE;
- desc.access = WINED3D_RESOURCE_ACCESS_CPU | WINED3D_RESOURCE_ACCESS_MAP;
+ desc.access = WINED3D_RESOURCE_ACCESS_CPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
desc.width = wined3d_texture_get_level_width(src_texture, texture_level);
desc.height = wined3d_texture_get_level_height(src_texture, texture_level);
desc.depth = 1;
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index 77ba007..58d4116 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -369,7 +369,7 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc
}
wined3d_resource_update_draw_binding(&texture->resource);
if ((flags & WINED3D_TEXTURE_CREATE_MAPPABLE) || desc->format == WINED3DFMT_D16_LOCKABLE)
- texture->resource.access |= WINED3D_RESOURCE_ACCESS_MAP;
+ texture->resource.access |= WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
texture->texture_ops = texture_ops;
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 78934af..10cfa25 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -4156,7 +4156,8 @@ const char *wined3d_debug_resource_access(DWORD access)
#define ACCESS_TO_STR(x) if (access & x) { strcat(buf, " | "#x); access &= ~x; }
ACCESS_TO_STR(WINED3D_RESOURCE_ACCESS_GPU);
ACCESS_TO_STR(WINED3D_RESOURCE_ACCESS_CPU);
- ACCESS_TO_STR(WINED3D_RESOURCE_ACCESS_MAP);
+ ACCESS_TO_STR(WINED3D_RESOURCE_ACCESS_MAP_R);
+ ACCESS_TO_STR(WINED3D_RESOURCE_ACCESS_MAP_W);
#undef ACCESS_TO_STR
if (access)
FIXME("Unrecognised access flag(s) %#x.\n", access);
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index f329c6f..b6a2ec3 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -52,7 +52,8 @@
#define WINED3D_RESOURCE_ACCESS_GPU 0x1u
#define WINED3D_RESOURCE_ACCESS_CPU 0x2u
-#define WINED3D_RESOURCE_ACCESS_MAP 0x4u
+#define WINED3D_RESOURCE_ACCESS_MAP_R 0x4u
+#define WINED3D_RESOURCE_ACCESS_MAP_W 0x8u
enum wined3d_light_type
{
--
2.1.4
1
0
[PATCH 1/5] wined3d: Introduce separate read and write resource map flags.
by Henri Verbeet 18 Feb '18
by Henri Verbeet 18 Feb '18
18 Feb '18
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/d3d11/utils.c | 12 +++++++-----
dlls/d3d8/device.c | 17 +++++++++++------
dlls/d3d9/device.c | 17 +++++++++++------
dlls/ddraw/device.c | 14 +++++++-------
dlls/ddraw/executebuffer.c | 7 +++----
dlls/ddraw/surface.c | 4 ++--
dlls/ddraw/utils.c | 11 ++++++++---
dlls/wined3d/buffer.c | 8 ++++----
dlls/wined3d/context.c | 4 ++--
dlls/wined3d/device.c | 8 ++++----
dlls/wined3d/resource.c | 38 +++++++++++++++++++++++++-------------
dlls/wined3d/surface.c | 17 +++++++++--------
dlls/wined3d/texture.c | 5 +++--
include/wine/wined3d.h | 13 +++++++------
14 files changed, 103 insertions(+), 72 deletions(-)
diff --git a/dlls/d3d11/utils.c b/dlls/d3d11/utils.c
index 3a48907..5c6add7 100644
--- a/dlls/d3d11/utils.c
+++ b/dlls/d3d11/utils.c
@@ -758,21 +758,23 @@ DWORD wined3d_map_flags_from_d3d11_map_type(D3D11_MAP map_type)
switch (map_type)
{
case D3D11_MAP_WRITE:
+ return WINED3D_MAP_WRITE;
+
case D3D11_MAP_READ_WRITE:
- return 0;
+ return WINED3D_MAP_READ | WINED3D_MAP_WRITE;
case D3D11_MAP_READ:
- return WINED3D_MAP_READONLY;
+ return WINED3D_MAP_READ;
case D3D11_MAP_WRITE_DISCARD:
- return WINED3D_MAP_DISCARD;
+ return WINED3D_MAP_WRITE | WINED3D_MAP_DISCARD;
case D3D11_MAP_WRITE_NO_OVERWRITE:
- return WINED3D_MAP_NOOVERWRITE;
+ return WINED3D_MAP_WRITE | WINED3D_MAP_NOOVERWRITE;
default:
FIXME("Unhandled map_type %#x.\n", map_type);
- return 0;
+ return WINED3D_MAP_READ | WINED3D_MAP_WRITE;
}
}
diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c
index fc40026..090d196 100644
--- a/dlls/d3d8/device.c
+++ b/dlls/d3d8/device.c
@@ -143,15 +143,20 @@ enum wined3d_format_id wined3dformat_from_d3dformat(D3DFORMAT format)
unsigned int wined3dmapflags_from_d3dmapflags(unsigned int flags)
{
- static const unsigned int handled = D3DLOCK_READONLY
- | D3DLOCK_NOSYSLOCK
+ static const unsigned int handled = D3DLOCK_NOSYSLOCK
| D3DLOCK_NOOVERWRITE
| D3DLOCK_DISCARD
| D3DLOCK_NO_DIRTY_UPDATE;
unsigned int wined3d_flags;
wined3d_flags = flags & handled;
- flags &= ~handled;
+ if (!(flags & (D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD)))
+ wined3d_flags |= WINED3D_MAP_READ;
+ if (!(flags & D3DLOCK_READONLY))
+ wined3d_flags |= WINED3D_MAP_WRITE;
+ if (!(wined3d_flags & (WINED3D_MAP_READ | WINED3D_MAP_WRITE)))
+ wined3d_flags |= WINED3D_MAP_READ | WINED3D_MAP_WRITE;
+ flags &= ~(handled | D3DLOCK_READONLY);
if (flags)
FIXME("Unhandled flags %#x.\n", flags);
@@ -2225,7 +2230,7 @@ static HRESULT WINAPI d3d8_device_DrawPrimitiveUP(IDirect3DDevice8 *iface,
wined3d_box.right = vb_pos + size;
vb = wined3d_buffer_get_resource(device->vertex_buffer);
if (FAILED(wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
- vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
+ WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
goto done;
memcpy(wined3d_map_desc.data, data, size);
wined3d_resource_unmap(vb, 0);
@@ -2326,7 +2331,7 @@ static HRESULT WINAPI d3d8_device_DrawIndexedPrimitiveUP(IDirect3DDevice8 *iface
wined3d_box.right = vb_pos + vtx_size;
vb = wined3d_buffer_get_resource(device->vertex_buffer);
if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
- vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
+ WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
goto done;
memcpy(wined3d_map_desc.data, (char *)vertex_data + min_vertex_idx * vertex_stride, vtx_size);
wined3d_resource_unmap(vb, 0);
@@ -2348,7 +2353,7 @@ static HRESULT WINAPI d3d8_device_DrawIndexedPrimitiveUP(IDirect3DDevice8 *iface
wined3d_box.right = ib_pos + idx_size;
ib = wined3d_buffer_get_resource(device->index_buffer);
if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
- ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
+ WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
goto done;
memcpy(wined3d_map_desc.data, index_data, idx_size);
wined3d_resource_unmap(ib, 0);
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c
index c057c77..b278d6d 100644
--- a/dlls/d3d9/device.c
+++ b/dlls/d3d9/device.c
@@ -162,8 +162,7 @@ enum wined3d_format_id wined3dformat_from_d3dformat(D3DFORMAT format)
unsigned int wined3dmapflags_from_d3dmapflags(unsigned int flags)
{
- static const unsigned int handled = D3DLOCK_READONLY
- | D3DLOCK_NOSYSLOCK
+ static const unsigned int handled = D3DLOCK_NOSYSLOCK
| D3DLOCK_NOOVERWRITE
| D3DLOCK_DISCARD
| D3DLOCK_DONOTWAIT
@@ -171,7 +170,13 @@ unsigned int wined3dmapflags_from_d3dmapflags(unsigned int flags)
unsigned int wined3d_flags;
wined3d_flags = flags & handled;
- flags &= ~handled;
+ if (!(flags & (D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD)))
+ wined3d_flags |= WINED3D_MAP_READ;
+ if (!(flags & D3DLOCK_READONLY))
+ wined3d_flags |= WINED3D_MAP_WRITE;
+ if (!(wined3d_flags & (WINED3D_MAP_READ | WINED3D_MAP_WRITE)))
+ wined3d_flags |= WINED3D_MAP_READ | WINED3D_MAP_WRITE;
+ flags &= ~(handled | D3DLOCK_READONLY);
if (flags)
FIXME("Unhandled flags %#x.\n", flags);
@@ -2737,7 +2742,7 @@ static HRESULT WINAPI d3d9_device_DrawPrimitiveUP(IDirect3DDevice9Ex *iface,
wined3d_box.right = vb_pos + size;
vb = wined3d_buffer_get_resource(device->vertex_buffer);
if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
- vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
+ WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
goto done;
memcpy(wined3d_map_desc.data, data, size);
wined3d_resource_unmap(vb, 0);
@@ -2848,7 +2853,7 @@ static HRESULT WINAPI d3d9_device_DrawIndexedPrimitiveUP(IDirect3DDevice9Ex *ifa
wined3d_box.right = vb_pos + vtx_size;
vb = wined3d_buffer_get_resource(device->vertex_buffer);
if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
- vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
+ WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
goto done;
memcpy(wined3d_map_desc.data, (char *)vertex_data + min_vertex_idx * vertex_stride, vtx_size);
wined3d_resource_unmap(vb, 0);
@@ -2870,7 +2875,7 @@ static HRESULT WINAPI d3d9_device_DrawIndexedPrimitiveUP(IDirect3DDevice9Ex *ifa
wined3d_box.right = ib_pos + idx_size;
ib = wined3d_buffer_get_resource(device->index_buffer);
if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
- ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
+ WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
goto done;
memcpy(wined3d_map_desc.data, index_data, idx_size);
wined3d_resource_unmap(ib, 0);
diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c
index d31d598..463d036 100644
--- a/dlls/ddraw/device.c
+++ b/dlls/ddraw/device.c
@@ -3533,7 +3533,7 @@ static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
wined3d_box.right = vb_pos + size;
vb = wined3d_buffer_get_resource(device->vertex_buffer);
if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
- vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
+ WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
goto done;
memcpy(wined3d_map_desc.data, vertices, size);
wined3d_resource_unmap(vb, 0);
@@ -3725,7 +3725,7 @@ static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
wined3d_box.right = vb_pos + vtx_size;
vb = wined3d_buffer_get_resource(device->vertex_buffer);
if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
- vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
+ WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
goto done;
memcpy(wined3d_map_desc.data, vertices, vtx_size);
wined3d_resource_unmap(vb, 0);
@@ -3742,7 +3742,7 @@ static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
wined3d_box.right = ib_pos + idx_size;
ib = wined3d_buffer_get_resource(device->index_buffer);
if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
- ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
+ WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
goto done;
memcpy(wined3d_map_desc.data, indices, idx_size);
wined3d_resource_unmap(ib, 0);
@@ -4056,7 +4056,7 @@ static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIM
wined3d_box.right = vb_pos + dst_size;
vb = wined3d_buffer_get_resource(device->vertex_buffer);
if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
- vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
+ WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
goto done;
pack_strided_data(wined3d_map_desc.data, vertex_count, strided_data, fvf);
wined3d_resource_unmap(vb, 0);
@@ -4172,7 +4172,7 @@ static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
wined3d_box.right = vb_pos + vtx_dst_size;
vb = wined3d_buffer_get_resource(device->vertex_buffer);
if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
- vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
+ WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
goto done;
pack_strided_data(wined3d_map_desc.data, vertex_count, strided_data, fvf);
wined3d_resource_unmap(vb, 0);
@@ -4189,7 +4189,7 @@ static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
wined3d_box.right = ib_pos + idx_size;
ib = wined3d_buffer_get_resource(device->index_buffer);
if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
- ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
+ WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
goto done;
memcpy(wined3d_map_desc.data, indices, idx_size);
wined3d_resource_unmap(ib, 0);
@@ -4409,7 +4409,7 @@ static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
wined3d_box.right = ib_pos + index_count * sizeof(WORD);
ib = wined3d_buffer_get_resource(device->index_buffer);
if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
- ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
+ WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
{
ERR("Failed to map buffer, hr %#x.\n", hr);
wined3d_mutex_unlock();
diff --git a/dlls/ddraw/executebuffer.c b/dlls/ddraw/executebuffer.c
index b47606a..19ef9c0 100644
--- a/dlls/ddraw/executebuffer.c
+++ b/dlls/ddraw/executebuffer.c
@@ -152,9 +152,8 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
box.left = index_pos * sizeof(*indices);
box.right = (index_pos + index_count) * sizeof(*indices);
- hr = wined3d_resource_map(wined3d_buffer_get_resource(buffer->index_buffer), 0,
- &map_desc, &box, index_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
- if (FAILED(hr))
+ if (FAILED(hr = wined3d_resource_map(wined3d_buffer_get_resource(buffer->index_buffer), 0, &map_desc,
+ &box, WINED3D_MAP_WRITE | (index_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
return hr;
indices = map_desc.data;
@@ -661,7 +660,7 @@ static HRESULT WINAPI d3d_execute_buffer_SetExecuteData(IDirect3DExecuteBuffer *
box.left = buffer->src_vertex_pos * sizeof(D3DVERTEX);
box.right = box.left + data->dwVertexCount * sizeof(D3DVERTEX);
if (FAILED(hr = wined3d_resource_map(wined3d_buffer_get_resource(buffer->src_vertex_buffer),
- 0, &map_desc, &box, 0)))
+ 0, &map_desc, &box, WINED3D_MAP_WRITE)))
return hr;
memcpy(map_desc.data, ((BYTE *)buffer->desc.lpData) + data->dwVertexOffset,
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c
index f09aaba..8280990 100644
--- a/dlls/ddraw/surface.c
+++ b/dlls/ddraw/surface.c
@@ -5281,7 +5281,7 @@ static HRESULT WINAPI d3d_texture2_Load(IDirect3DTexture2 *iface, IDirect3DTextu
}
if (FAILED(hr = wined3d_resource_map(src_resource,
- src_surface->sub_resource_idx, &src_map_desc, NULL, 0)))
+ src_surface->sub_resource_idx, &src_map_desc, NULL, WINED3D_MAP_READ)))
{
ERR("Failed to lock source surface, hr %#x.\n", hr);
wined3d_mutex_unlock();
@@ -5289,7 +5289,7 @@ static HRESULT WINAPI d3d_texture2_Load(IDirect3DTexture2 *iface, IDirect3DTextu
}
if (FAILED(hr = wined3d_resource_map(dst_resource,
- dst_surface->sub_resource_idx, &dst_map_desc, NULL, 0)))
+ dst_surface->sub_resource_idx, &dst_map_desc, NULL, WINED3D_MAP_WRITE)))
{
ERR("Failed to lock destination surface, hr %#x.\n", hr);
wined3d_resource_unmap(src_resource, src_surface->sub_resource_idx);
diff --git a/dlls/ddraw/utils.c b/dlls/ddraw/utils.c
index bb75666..0170fcd 100644
--- a/dlls/ddraw/utils.c
+++ b/dlls/ddraw/utils.c
@@ -563,17 +563,22 @@ enum wined3d_format_id wined3dformat_from_ddrawformat(const DDPIXELFORMAT *DDPix
unsigned int wined3dmapflags_from_ddrawmapflags(unsigned int flags)
{
- static const unsigned int handled = DDLOCK_READONLY
- | DDLOCK_NOSYSLOCK
+ static const unsigned int handled = DDLOCK_NOSYSLOCK
| DDLOCK_NOOVERWRITE
| DDLOCK_DISCARDCONTENTS
| DDLOCK_DONOTWAIT;
unsigned int wined3d_flags;
wined3d_flags = flags & handled;
+ if (!(flags & (DDLOCK_NOOVERWRITE | DDLOCK_DISCARDCONTENTS)))
+ wined3d_flags |= WINED3D_MAP_READ;
+ if (!(flags & DDLOCK_READONLY))
+ wined3d_flags |= WINED3D_MAP_WRITE;
+ if (!(wined3d_flags & (WINED3D_MAP_READ | WINED3D_MAP_WRITE)))
+ wined3d_flags |= WINED3D_MAP_READ | WINED3D_MAP_WRITE;
if (flags & DDLOCK_NODIRTYUPDATE)
wined3d_flags |= WINED3D_MAP_NO_DIRTY_UPDATE;
- flags &= ~(handled | DDLOCK_WAIT | DDLOCK_NODIRTYUPDATE);
+ flags &= ~(handled | DDLOCK_WAIT | DDLOCK_READONLY | DDLOCK_NODIRTYUPDATE);
if (flags)
FIXME("Unhandled flags %#x.\n", flags);
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index c1dfc56..1055326 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -1024,8 +1024,8 @@ static HRESULT wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UI
dirty_size = 0;
}
- if (!(flags & (WINED3D_MAP_NOOVERWRITE | WINED3D_MAP_DISCARD | WINED3D_MAP_READONLY))
- || ((flags & WINED3D_MAP_READONLY) && (buffer->locations & WINED3D_LOCATION_SYSMEM))
+ if (((flags & WINED3D_MAP_WRITE) && !(flags & (WINED3D_MAP_NOOVERWRITE | WINED3D_MAP_DISCARD)))
+ || (!(flags & WINED3D_MAP_WRITE) && (buffer->locations & WINED3D_LOCATION_SYSMEM))
|| buffer->flags & WINED3D_BUFFER_PIN_SYSMEM)
{
if (!(buffer->locations & WINED3D_LOCATION_SYSMEM))
@@ -1035,7 +1035,7 @@ static HRESULT wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UI
context_release(context);
}
- if (!(flags & WINED3D_MAP_READONLY))
+ if (flags & WINED3D_MAP_WRITE)
wined3d_buffer_invalidate_range(buffer, WINED3D_LOCATION_BUFFER, dirty_offset, dirty_size);
}
else
@@ -1050,7 +1050,7 @@ static HRESULT wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UI
else
wined3d_buffer_load_location(buffer, context, WINED3D_LOCATION_BUFFER);
- if (!(flags & WINED3D_MAP_READONLY))
+ if (flags & WINED3D_MAP_WRITE)
buffer_invalidate_bo_range(buffer, dirty_offset, dirty_size);
if ((flags & WINED3D_MAP_DISCARD) && buffer->resource.heap_memory)
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index b97dff5..9b6c19e 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -2837,8 +2837,8 @@ void context_copy_bo_address(struct wined3d_context *context,
}
else
{
- src_ptr = context_map_bo_address(context, src, size, src_binding, WINED3D_MAP_READONLY);
- dst_ptr = context_map_bo_address(context, dst, size, dst_binding, 0);
+ src_ptr = context_map_bo_address(context, src, size, src_binding, WINED3D_MAP_READ);
+ dst_ptr = context_map_bo_address(context, dst, size, dst_binding, WINED3D_MAP_WRITE);
memcpy(dst_ptr, src_ptr, size);
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 17103cc..6e275e1 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -3078,7 +3078,7 @@ static HRESULT process_vertices_strided(const struct wined3d_device *device, DWO
vertex_size = get_flexible_vertex_size(DestFVF);
box.left = dwDestIndex * vertex_size;
box.right = box.left + dwCount * vertex_size;
- if (FAILED(hr = wined3d_resource_map(&dest->resource, 0, &map_desc, &box, 0)))
+ if (FAILED(hr = wined3d_resource_map(&dest->resource, 0, &map_desc, &box, WINED3D_MAP_WRITE)))
{
WARN("Failed to map buffer, hr %#x.\n", hr);
return hr;
@@ -3342,7 +3342,7 @@ HRESULT CDECL wined3d_device_process_vertices(struct wined3d_device *device,
resource = &state->streams[e->stream_idx].buffer->resource;
box.left = src_start_idx * e->stride;
box.right = box.left + vertex_count * e->stride;
- if (FAILED(wined3d_resource_map(resource, 0, &map_desc, &box, WINED3D_MAP_READONLY)))
+ if (FAILED(wined3d_resource_map(resource, 0, &map_desc, &box, WINED3D_MAP_READ)))
ERR("Failed to map resource.\n");
e->data.buffer_object = 0;
e->data.addr += (ULONG_PTR)map_desc.data;
@@ -4499,7 +4499,7 @@ static struct wined3d_texture *wined3d_device_create_cursor_texture(struct wined
struct wined3d_texture *texture;
HRESULT hr;
- if (FAILED(wined3d_resource_map(&cursor_image->resource, sub_resource_idx, &map_desc, NULL, WINED3D_MAP_READONLY)))
+ if (FAILED(wined3d_resource_map(&cursor_image->resource, sub_resource_idx, &map_desc, NULL, WINED3D_MAP_READ)))
{
ERR("Failed to map source texture.\n");
return NULL;
@@ -4603,7 +4603,7 @@ HRESULT CDECL wined3d_device_set_cursor_properties(struct wined3d_device *device
memset(mask_bits, 0xff, mask_size);
wined3d_resource_map(&texture->resource, sub_resource_idx, &map_desc, NULL,
- WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY);
+ WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READ);
cursor_info.fIcon = FALSE;
cursor_info.xHotspot = x_hotspot;
cursor_info.yHotspot = y_hotspot;
diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c
index ddc157b..ac36183 100644
--- a/dlls/wined3d/resource.c
+++ b/dlls/wined3d/resource.c
@@ -306,17 +306,17 @@ static DWORD wined3d_resource_sanitise_map_flags(const struct wined3d_resource *
{
/* Not all flags make sense together, but Windows never returns an error.
* Catch the cases that could cause issues. */
- if (flags & WINED3D_MAP_READONLY)
+ if (flags & WINED3D_MAP_READ)
{
if (flags & WINED3D_MAP_DISCARD)
{
- WARN("WINED3D_MAP_READONLY combined with WINED3D_MAP_DISCARD, ignoring flags.\n");
- return 0;
+ WARN("WINED3D_MAP_READ combined with WINED3D_MAP_DISCARD, ignoring flags.\n");
+ return flags & (WINED3D_MAP_READ | WINED3D_MAP_WRITE);
}
if (flags & WINED3D_MAP_NOOVERWRITE)
{
- WARN("WINED3D_MAP_READONLY combined with WINED3D_MAP_NOOVERWRITE, ignoring flags.\n");
- return 0;
+ WARN("WINED3D_MAP_READ combined with WINED3D_MAP_NOOVERWRITE, ignoring flags.\n");
+ return flags & (WINED3D_MAP_READ | WINED3D_MAP_WRITE);
}
}
else if (flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE))
@@ -324,7 +324,7 @@ static DWORD wined3d_resource_sanitise_map_flags(const struct wined3d_resource *
if (!(resource->usage & WINED3DUSAGE_DYNAMIC))
{
WARN("DISCARD or NOOVERWRITE map on non-dynamic buffer, ignoring.\n");
- return 0;
+ return flags & (WINED3D_MAP_READ | WINED3D_MAP_WRITE);
}
if ((flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE))
== (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE))
@@ -343,6 +343,12 @@ HRESULT CDECL wined3d_resource_map(struct wined3d_resource *resource, unsigned i
TRACE("resource %p, sub_resource_idx %u, map_desc %p, box %s, flags %#x.\n",
resource, sub_resource_idx, map_desc, debug_box(box), flags);
+ if (!(flags & (WINED3D_MAP_READ | WINED3D_MAP_WRITE)))
+ {
+ WARN("No read/write flags specified.\n");
+ return E_INVALIDARG;
+ }
+
if (!(resource->access & WINED3D_RESOURCE_ACCESS_MAP))
{
WARN("Resource is not mappable.\n");
@@ -399,9 +405,9 @@ GLbitfield wined3d_resource_gl_map_flags(DWORD d3d_flags)
{
GLbitfield ret = 0;
- if (!(d3d_flags & WINED3D_MAP_READONLY))
+ if (d3d_flags & WINED3D_MAP_WRITE)
ret |= GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT;
- if (!(d3d_flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE)))
+ if (d3d_flags & WINED3D_MAP_READ)
ret |= GL_MAP_READ_BIT;
if (d3d_flags & WINED3D_MAP_DISCARD)
@@ -414,11 +420,17 @@ GLbitfield wined3d_resource_gl_map_flags(DWORD d3d_flags)
GLenum wined3d_resource_gl_legacy_map_flags(DWORD d3d_flags)
{
- if (d3d_flags & WINED3D_MAP_READONLY)
- return GL_READ_ONLY_ARB;
- if (d3d_flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE))
- return GL_WRITE_ONLY_ARB;
- return GL_READ_WRITE_ARB;
+ switch (d3d_flags & (WINED3D_MAP_READ | WINED3D_MAP_WRITE))
+ {
+ case WINED3D_MAP_READ:
+ return GL_READ_ONLY_ARB;
+
+ case WINED3D_MAP_WRITE:
+ return GL_WRITE_ONLY_ARB;
+
+ default:
+ return GL_READ_WRITE_ARB;
+ }
}
BOOL wined3d_resource_is_offscreen(struct wined3d_resource *resource)
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 5cb9cda..7cf9c21 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -1369,9 +1369,9 @@ static struct wined3d_texture *surface_convert_format(struct wined3d_texture *sr
wined3d_texture_get_memory(dst_texture, 0, &dst_data, map_binding);
src = context_map_bo_address(context, &src_data,
- src_texture->sub_resources[sub_resource_idx].size, GL_PIXEL_UNPACK_BUFFER, 0);
+ src_texture->sub_resources[sub_resource_idx].size, GL_PIXEL_UNPACK_BUFFER, WINED3D_MAP_READ);
dst = context_map_bo_address(context,
- &dst_data, dst_texture->sub_resources[0].size, GL_PIXEL_UNPACK_BUFFER, 0);
+ &dst_data, dst_texture->sub_resources[0].size, GL_PIXEL_UNPACK_BUFFER, WINED3D_MAP_WRITE);
conv->convert(src, dst, src_row_pitch, dst_row_pitch, desc.width, desc.height);
@@ -2325,7 +2325,7 @@ static BOOL surface_load_texture(struct wined3d_surface *surface,
wined3d_format_calculate_pitch(&format, 1, width, height, &dst_row_pitch, &dst_slice_pitch);
src_mem = context_map_bo_address(context, &data, src_slice_pitch,
- GL_PIXEL_UNPACK_BUFFER, WINED3D_MAP_READONLY);
+ GL_PIXEL_UNPACK_BUFFER, WINED3D_MAP_READ);
if (!(dst_mem = heap_alloc(dst_slice_pitch)))
{
ERR("Out of memory (%u).\n", dst_slice_pitch);
@@ -2349,7 +2349,7 @@ static BOOL surface_load_texture(struct wined3d_surface *surface,
width, height, &dst_row_pitch, &dst_slice_pitch);
src_mem = context_map_bo_address(context, &data, src_slice_pitch,
- GL_PIXEL_UNPACK_BUFFER, WINED3D_MAP_READONLY);
+ GL_PIXEL_UNPACK_BUFFER, WINED3D_MAP_READ);
if (!(dst_mem = heap_alloc(dst_slice_pitch)))
{
ERR("Out of memory (%u).\n", dst_slice_pitch);
@@ -3113,7 +3113,8 @@ static HRESULT surface_cpu_blt(struct wined3d_texture *dst_texture, unsigned int
wined3d_texture_get_pitch(dst_texture, texture_level, &dst_map.row_pitch, &dst_map.slice_pitch);
wined3d_texture_get_memory(dst_texture, dst_sub_resource_idx, &dst_data, map_binding);
dst_map.data = context_map_bo_address(context, &dst_data,
- dst_texture->sub_resources[dst_sub_resource_idx].size, GL_PIXEL_UNPACK_BUFFER, 0);
+ dst_texture->sub_resources[dst_sub_resource_idx].size,
+ GL_PIXEL_UNPACK_BUFFER, WINED3D_MAP_READ | WINED3D_MAP_WRITE);
src_map = dst_map;
src_format = dst_texture->resource.format;
@@ -3149,7 +3150,7 @@ static HRESULT surface_cpu_blt(struct wined3d_texture *dst_texture, unsigned int
wined3d_texture_get_pitch(src_texture, texture_level, &src_map.row_pitch, &src_map.slice_pitch);
wined3d_texture_get_memory(src_texture, src_sub_resource_idx, &src_data, map_binding);
src_map.data = context_map_bo_address(context, &src_data,
- src_texture->sub_resources[src_sub_resource_idx].size, GL_PIXEL_UNPACK_BUFFER, 0);
+ src_texture->sub_resources[src_sub_resource_idx].size, GL_PIXEL_UNPACK_BUFFER, WINED3D_MAP_READ);
map_binding = dst_texture->resource.map_binding;
texture_level = dst_sub_resource_idx % dst_texture->level_count;
@@ -3159,7 +3160,7 @@ static HRESULT surface_cpu_blt(struct wined3d_texture *dst_texture, unsigned int
wined3d_texture_get_pitch(dst_texture, texture_level, &dst_map.row_pitch, &dst_map.slice_pitch);
wined3d_texture_get_memory(dst_texture, dst_sub_resource_idx, &dst_data, map_binding);
dst_map.data = context_map_bo_address(context, &dst_data,
- dst_texture->sub_resources[dst_sub_resource_idx].size, GL_PIXEL_UNPACK_BUFFER, 0);
+ dst_texture->sub_resources[dst_sub_resource_idx].size, GL_PIXEL_UNPACK_BUFFER, WINED3D_MAP_WRITE);
}
flags &= ~WINED3D_BLT_RAW;
@@ -3600,7 +3601,7 @@ static void surface_cpu_blt_colour_fill(struct wined3d_rendertarget_view *view,
&map.row_pitch, &map.slice_pitch);
wined3d_texture_get_memory(texture, view->sub_resource_idx, &data, map_binding);
map.data = context_map_bo_address(context, &data,
- texture->sub_resources[view->sub_resource_idx].size, GL_PIXEL_UNPACK_BUFFER, 0);
+ texture->sub_resources[view->sub_resource_idx].size, GL_PIXEL_UNPACK_BUFFER, WINED3D_MAP_WRITE);
map.data = (BYTE *)map.data
+ (box->front * map.slice_pitch)
+ ((box->top / view->format->block_height) * map.row_pitch)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index 57e6427..77ba007 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -1224,7 +1224,8 @@ static void texture2d_create_dc(void *object)
wined3d_texture_get_pitch(texture, surface->texture_level, &row_pitch, &slice_pitch);
wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding);
desc.pMemory = context_map_bo_address(context, &data,
- texture->sub_resources[sub_resource_idx].size, GL_PIXEL_UNPACK_BUFFER, 0);
+ texture->sub_resources[sub_resource_idx].size,
+ GL_PIXEL_UNPACK_BUFFER, WINED3D_MAP_READ | WINED3D_MAP_WRITE);
if (context)
context_release(context);
@@ -1903,7 +1904,7 @@ static HRESULT texture_resource_sub_resource_map(struct wined3d_resource *resour
return E_OUTOFMEMORY;
}
- if (!(flags & WINED3D_MAP_READONLY)
+ if (flags & WINED3D_MAP_WRITE
&& (!(flags & WINED3D_MAP_NO_DIRTY_UPDATE) || (resource->usage & WINED3DUSAGE_DYNAMIC)))
wined3d_texture_invalidate_location(texture, sub_resource_idx, ~resource->map_binding);
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index 1e3c08b..f329c6f 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -912,12 +912,13 @@ enum wined3d_shader_byte_code_format
#define WINED3DUSAGE_QUERY_WRAPANDMIP 0x00200000
#define WINED3DUSAGE_QUERY_MASK 0x003f8400
-#define WINED3D_MAP_READONLY 0x0010
-#define WINED3D_MAP_NOSYSLOCK 0x0800
-#define WINED3D_MAP_NOOVERWRITE 0x1000
-#define WINED3D_MAP_DISCARD 0x2000
-#define WINED3D_MAP_DONOTWAIT 0x4000
-#define WINED3D_MAP_NO_DIRTY_UPDATE 0x8000
+#define WINED3D_MAP_NOSYSLOCK 0x00000800
+#define WINED3D_MAP_NOOVERWRITE 0x00001000
+#define WINED3D_MAP_DISCARD 0x00002000
+#define WINED3D_MAP_DONOTWAIT 0x00004000
+#define WINED3D_MAP_NO_DIRTY_UPDATE 0x00008000
+#define WINED3D_MAP_WRITE 0x40000000
+#define WINED3D_MAP_READ 0x80000000
#define WINED3DPRESENT_RATE_DEFAULT 0x00000000
--
2.1.4
1
0
18 Feb '18
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/shell32/tests/shlview.c | 30 ++++++++++++++++++++++++++++++
include/shlguid.h | 1 +
2 files changed, 31 insertions(+)
diff --git a/dlls/shell32/tests/shlview.c b/dlls/shell32/tests/shlview.c
index 76855067c0..f31d16e5e2 100644
--- a/dlls/shell32/tests/shlview.c
+++ b/dlls/shell32/tests/shlview.c
@@ -1476,6 +1476,35 @@ if (0)
IShellFolder_Release(desktop);
}
+static void test_newmenu(void)
+{
+ IUnknown *unk, *unk2;
+ HRESULT hr;
+
+ hr = CoCreateInstance(&CLSID_NewMenu, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk);
+todo_wine
+ ok(hr == S_OK, "Failed to create NewMenu object, hr %#x.\n", hr);
+ if (hr != S_OK)
+ {
+ skip("NewMenu is not supported.\n");
+ return;
+ }
+
+ hr = IUnknown_QueryInterface(unk, &IID_IShellExtInit, (void **)&unk2);
+ ok(hr == S_OK, "Failed to get IShellExtInit, hr %#x.\n", hr);
+ IUnknown_Release(unk2);
+
+ hr = IUnknown_QueryInterface(unk, &IID_IContextMenu3, (void **)&unk2);
+ ok(hr == S_OK, "Failed to get IContextMenu3, hr %#x.\n", hr);
+ IUnknown_Release(unk2);
+
+ hr = IUnknown_QueryInterface(unk, &IID_IObjectWithSite, (void **)&unk2);
+ ok(hr == S_OK, "Failed to get IObjectWithSite, hr %#x.\n", hr);
+ IUnknown_Release(unk2);
+
+ IUnknown_Release(unk);
+}
+
START_TEST(shlview)
{
OleInitialize(NULL);
@@ -1491,6 +1520,7 @@ START_TEST(shlview)
test_IOleCommandTarget();
test_SHCreateShellFolderView();
test_SHCreateShellFolderViewEx();
+ test_newmenu();
OleUninitialize();
}
diff --git a/include/shlguid.h b/include/shlguid.h
index 028cb61f28..687bbec79e 100644
--- a/include/shlguid.h
+++ b/include/shlguid.h
@@ -146,6 +146,7 @@ DEFINE_GUID(CLSID_DragDropHelper, 0x4657278a, 0x411b, 0x11d2, 0x83, 0x9a, 0x00,
DEFINE_GUID(CLSID_ProgressDialog, 0xf8383852, 0xfcd3, 0x11d1, 0xa6, 0xb9, 0x0, 0x60, 0x97, 0xdf, 0x5b, 0xd4);
DEFINE_GUID(CLSID_ShellItem, 0x2fe352ea, 0xfd1f, 0x11d2, 0xb1, 0xf4, 0x00, 0xc0, 0x4f, 0x8e, 0xeb, 0x3e);
+DEFINE_GUID(CLSID_NewMenu, 0xd969a300, 0xe7ff, 0x11d0, 0xa9, 0x3b, 0x0, 0xa0, 0xc9, 0xf, 0x27, 0x19);
#define PSGUID_SHELLDETAILS {0x28636aa6, 0x953d, 0x11d2, 0xb5, 0xd6, 0x0, 0xc0, 0x4f, 0xd9, 0x18, 0xd0}
DEFINE_GUID(FMTID_ShellDetails, 0x28636aa6, 0x953d, 0x11d2, 0xb5, 0xd6, 0x0, 0xc0, 0x4f, 0xd9, 0x18, 0xd0);
--
2.16.1
1
4
[PATCH v2] uiribbon.idl: Add UIRibbonImageFromBitmapFactory coclass and more interface definitions
by Fabian Maurer 18 Feb '18
by Fabian Maurer 18 Feb '18
18 Feb '18
v2: Make enums [v1_enum]
Signed-off-by: Fabian Maurer <dark.shadow4(a)web.de>
---
include/uiribbon.idl | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 128 insertions(+)
diff --git a/include/uiribbon.idl b/include/uiribbon.idl
index 6759400be5..efb70d8e4f 100644
--- a/include/uiribbon.idl
+++ b/include/uiribbon.idl
@@ -64,6 +64,17 @@ typedef enum UI_COMMANDTYPE {
UI_COMMANDTYPE_COLORCOLLECTION,
} UI_COMMANDTYPE;
+typedef [v1_enum] enum UI_OWNERSHIP {
+ UI_OWNERSHIP_TRANSFER = 0,
+ UI_OWNERSHIP_COPY = 1,
+} UI_OWNERSHIP;
+
+typedef [v1_enum] enum UI_COLLECTIONCHANGE {
+ UI_COLLECTIONCHANGE_INSERT = 0,
+ UI_COLLECTIONCHANGE_REMOVE = 1,
+ UI_COLLECTIONCHANGE_REPLACE = 2,
+ UI_COLLECTIONCHANGE_RESET = 3
+} UI_COLLECTIONCHANGE;
[
object,
@@ -174,9 +185,126 @@ interface IUIFramework : IUnknown
);
}
+[
+ object,
+ uuid(23c8c838-4de6-436b-ab01-5554bb7c30dd),
+ local,
+ pointer_default(unique)
+]
+interface IUIImage : IUnknown
+{
+ HRESULT GetBitmap(
+ [out] HBITMAP *bitmap
+ );
+}
+
+[
+ object,
+ uuid(803982ab-370a-4f7e-a9e7-8784036a6e26),
+ local,
+ pointer_default(unique)
+]
+interface IUIRibbon : IUnknown
+{
+ HRESULT GetHeight(
+ [out] UINT32 *cy
+ );
+ HRESULT LoadSettingsFromStream(
+ [in] IStream *pStream
+ );
+ HRESULT SaveSettingsToStream(
+ [in] IStream *pStream
+ );
+}
+
+[
+ object,
+ uuid(df4f45bf-6f9d-4dd7-9d68-d8f9cd18c4db),
+ local,
+ pointer_default(unique)
+]
+interface IUICollection : IUnknown
+{
+ HRESULT GetCount(
+ [out] UINT32 *count
+ );
+ HRESULT GetItem(
+ [in] UINT32 index,
+ [out] IUnknown **item
+ );
+ HRESULT Add(
+ [in] IUnknown *item
+ );
+ HRESULT Insert(
+ [in] UINT32 index,
+ [in] IUnknown *item
+ );
+ HRESULT RemoveAt(
+ [in] UINT32 index
+ );
+ HRESULT Replace(
+ [in] UINT32 indexReplaced,
+ [in] IUnknown *itemReplaceWith
+ );
+ HRESULT Clear();
+}
+
+[
+ object,
+ uuid(eea11f37-7c46-437c-8e55-b52122b29293),
+ local,
+ pointer_default(unique)
+]
+interface IUIContextualUI : IUnknown
+{
+ HRESULT ShowAtLocation(
+ INT32 x,
+ INT32 y
+ );
+}
+
+[
+ object,
+ uuid(6502ae91-a14d-44b5-bbd0-62aacc581d52),
+ local,
+ pointer_default(unique)
+]
+interface IUICollectionChangedEvent : IUnknown
+{
+ HRESULT OnChanged(
+ [in] UI_COLLECTIONCHANGE action,
+ [in] UINT32 oldIndex,
+ [in] IUnknown *oldItem,
+ [in] UINT32 newIndex,
+ [in] IUnknown *newItem
+ );
+}
+
+[
+ object,
+ uuid(18aba7f3-4c1c-4ba2-bf6c-f5c3326fa816),
+ local,
+ pointer_default(unique)
+]
+interface IUIImageFromBitmap : IUnknown
+{
+ HRESULT CreateImage(
+ [in] HBITMAP bitmap,
+ [in] UI_OWNERSHIP options,
+ [out] IUIImage **image
+ );
+}
+
+
[
helpstring("UIRibbonFramework Object"),
threading(apartment),
uuid(926749fa-2615-4987-8845-c33e65f2b957)
]
coclass UIRibbonFramework { interface IUIFramework; }
+
+[
+ threading(apartment),
+ uuid(0f7434b6-59b6-4250-999e-d168d6ae4293)
+]
+coclass UIRibbonImageFromBitmapFactory { interface IUIImageFromBitmap; }
--
2.16.2
1
0