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
November 2020
- 73 participants
- 650 discussions
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/sti/sti.c | 17 ++++-------------
dlls/sti/tests/sti.c | 2 +-
2 files changed, 5 insertions(+), 14 deletions(-)
diff --git a/dlls/sti/sti.c b/dlls/sti/sti.c
index 962371f92d2..0bb60382979 100644
--- a/dlls/sti/sti.c
+++ b/dlls/sti/sti.c
@@ -32,14 +32,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(sti);
-static const WCHAR registeredAppsLaunchPath[] = {
- 'S','O','F','T','W','A','R','E','\\',
- 'M','i','c','r','o','s','o','f','t','\\',
- 'W','i','n','d','o','w','s','\\',
- 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
- 'S','t','i','l','l','I','m','a','g','e','\\',
- 'R','e','g','i','s','t','e','r','e','d',' ','A','p','p','l','i','c','a','t','i','o','n','s',0
-};
+static const WCHAR registeredAppsLaunchPath[] =
+ L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\StillImage\\Registered Applications";
typedef struct _stillimage
{
@@ -134,10 +128,7 @@ static HRESULT WINAPI stillimagew_GetSTILaunchInformation(IStillImageW *iface, L
static HRESULT WINAPI stillimagew_RegisterLaunchApplication(IStillImageW *iface, LPWSTR pwszAppName,
LPWSTR pwszCommandLine)
{
- static const WCHAR format[] = {'%','s',' ','%','s',0};
- static const WCHAR commandLineSuffix[] = {
- '/','S','t','i','D','e','v','i','c','e',':','%','1',' ',
- '/','S','t','i','E','v','e','n','t',':','%','2',0};
+ static const WCHAR commandLineSuffix[] = L"/StiDevice:%1 /StiEvent:%2";
HKEY registeredAppsKey = NULL;
DWORD ret;
HRESULT hr = S_OK;
@@ -152,7 +143,7 @@ static HRESULT WINAPI stillimagew_RegisterLaunchApplication(IStillImageW *iface,
WCHAR *value = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
if (value)
{
- swprintf(value, len, format, pwszCommandLine, commandLineSuffix);
+ swprintf(value, len, L"%s %s", pwszCommandLine, commandLineSuffix);
ret = RegSetValueExW(registeredAppsKey, pwszAppName, 0,
REG_SZ, (BYTE*)value, (lstrlenW(value)+1)*sizeof(WCHAR));
if (ret != ERROR_SUCCESS)
diff --git a/dlls/sti/tests/sti.c b/dlls/sti/tests/sti.c
index bd8b7b6b171..a87ab9fe47e 100644
--- a/dlls/sti/tests/sti.c
+++ b/dlls/sti/tests/sti.c
@@ -230,7 +230,7 @@ static void test_stillimage_aggregation(void)
static void test_launch_app_registry(void)
{
- static WCHAR appName[] = {'w','i','n','e','s','t','i','t','e','s','t','a','p','p',0};
+ static WCHAR appName[] = L"winestitestapp";
IStillImageW *pStiW = NULL;
HRESULT hr;
--
2.26.2
1
0
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/cryptdlg/main.c | 91 ++++++++++++++++----------------------------
1 file changed, 33 insertions(+), 58 deletions(-)
diff --git a/dlls/cryptdlg/main.c b/dlls/cryptdlg/main.c
index 4812ac9e621..e74ce0f48e7 100644
--- a/dlls/cryptdlg/main.c
+++ b/dlls/cryptdlg/main.c
@@ -109,21 +109,15 @@ HRESULT WINAPI CertTrustCleanup(CRYPT_PROVIDER_DATA *pProvData)
static BOOL CRYPTDLG_CheckOnlineCRL(void)
{
- static const WCHAR policyFlagsKey[] = { 'S','o','f','t','w','a','r','e',
- '\\','M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g',
- 'r','a','p','h','y','\\','{','7','8','0','1','e','b','d','0','-','c','f',
- '4','b','-','1','1','d','0','-','8','5','1','f','-','0','0','6','0','9',
- '7','9','3','8','7','e','a','}',0 };
- static const WCHAR policyFlags[] = { 'P','o','l','i','c','y','F','l','a',
- 'g','s',0 };
HKEY key;
BOOL ret = FALSE;
- if (!RegOpenKeyExW(HKEY_LOCAL_MACHINE, policyFlagsKey, 0, KEY_READ, &key))
+ if (!RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ L"Software\\Microsoft\\Cryptography\\{7801ebd0-cf4b-11d0-851f-0060979387ea}", 0, KEY_READ, &key))
{
DWORD type, flags, size = sizeof(flags);
- if (!RegQueryValueExW(key, policyFlags, NULL, &type, (BYTE *)&flags,
+ if (!RegQueryValueExW(key, L"PolicyFlags", NULL, &type, (BYTE *)&flags,
&size) && type == REG_DWORD)
{
/* The flag values aren't defined in any header I'm aware of, but
@@ -149,10 +143,8 @@ static BOOL CRYPTDLG_IsCertAllowed(PCCERT_CONTEXT pCert)
if ((ret = CertGetCertificateContextProperty(pCert,
CERT_SIGNATURE_HASH_PROP_ID, hash, &size)))
{
- static const WCHAR disallowedW[] =
- { 'D','i','s','a','l','l','o','w','e','d',0 };
HCERTSTORE disallowed = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
- X509_ASN_ENCODING, 0, CERT_SYSTEM_STORE_CURRENT_USER, disallowedW);
+ X509_ASN_ENCODING, 0, CERT_SYSTEM_STORE_CURRENT_USER, L"Disallowed");
if (disallowed)
{
@@ -487,8 +479,6 @@ static BOOL CRYPT_FormatHexString(const BYTE *pbEncoded, DWORD cbEncoded,
}
else
{
- static const WCHAR fmt[] = { '%','0','2','x',' ',0 };
- static const WCHAR endFmt[] = { '%','0','2','x',0 };
DWORD i;
LPWSTR ptr = str;
@@ -498,9 +488,9 @@ static BOOL CRYPT_FormatHexString(const BYTE *pbEncoded, DWORD cbEncoded,
for (i = 0; i < cbEncoded; i++)
{
if (i < cbEncoded - 1)
- ptr += swprintf(ptr, 4, fmt, pbEncoded[i]);
+ ptr += swprintf(ptr, 4, L"%02x ", pbEncoded[i]);
else
- ptr += swprintf(ptr, 3, endFmt, pbEncoded[i]);
+ ptr += swprintf(ptr, 3, L"%02x", pbEncoded[i]);
}
}
else
@@ -510,11 +500,7 @@ static BOOL CRYPT_FormatHexString(const BYTE *pbEncoded, DWORD cbEncoded,
return ret;
}
-static const WCHAR indent[] = { ' ',' ',' ',' ',' ',0 };
-static const WCHAR colonCrlf[] = { ':','\r','\n',0 };
-static const WCHAR colonSpace[] = { ':',' ',0 };
-static const WCHAR crlf[] = { '\r','\n',0 };
-static const WCHAR commaSep[] = { ',',' ',0 };
+static const WCHAR indent[] = L" ";
static BOOL CRYPT_FormatCPS(DWORD dwCertEncodingType,
DWORD dwFormatStrType, const BYTE *pbEncoded, DWORD cbEncoded,
@@ -531,9 +517,9 @@ static BOOL CRYPT_FormatCPS(DWORD dwCertEncodingType,
DWORD sepLen;
if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
- sep = crlf;
+ sep = L"\r\n";
else
- sep = commaSep;
+ sep = L", ";
sepLen = lstrlenW(sep);
@@ -589,7 +575,6 @@ static BOOL CRYPT_FormatUserNotice(DWORD dwCertEncodingType,
X509_PKIX_POLICY_QUALIFIER_USERNOTICE, pbEncoded, cbEncoded,
CRYPT_DECODE_ALLOC_FLAG, NULL, ¬ice, &size)))
{
- static const WCHAR numFmt[] = { '%','d',0 };
CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *pNoticeRef =
notice->pNoticeReference;
LPCWSTR headingSep, sep;
@@ -608,13 +593,13 @@ static BOOL CRYPT_FormatUserNotice(DWORD dwCertEncodingType,
(LPWSTR)¬iceText, 0);
if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
{
- headingSep = colonCrlf;
- sep = crlf;
+ headingSep = L":\r\n";
+ sep = L"\r\n";
}
else
{
- headingSep = colonSpace;
- sep = commaSep;
+ headingSep = L": ";
+ sep = L", ";
}
sepLen = lstrlenW(sep);
headingSepLen = lstrlenW(headingSep);
@@ -704,7 +689,7 @@ static BOOL CRYPT_FormatUserNotice(DWORD dwCertEncodingType,
memcpy(str, noticeNum, noticeNumLen * sizeof(WCHAR));
str += noticeNumLen;
}
- swprintf(noticeNumStr, ARRAY_SIZE(noticeNumStr), numFmt, k + 1);
+ swprintf(noticeNumStr, ARRAY_SIZE(noticeNumStr), L"%d", k + 1);
charsNeeded += lstrlenW(noticeNumStr);
if (str && *pcchStr >= charsNeeded)
{
@@ -788,7 +773,6 @@ BOOL WINAPI FormatVerisignExtension(DWORD dwCertEncodingType,
if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CERT_POLICIES,
pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &policies, &size)))
{
- static const WCHAR numFmt[] = { '%','d',0 };
DWORD charsNeeded = 1; /* space for NULL terminator */
LPCWSTR headingSep, sep;
DWORD headingSepLen, sepLen;
@@ -815,13 +799,13 @@ BOOL WINAPI FormatVerisignExtension(DWORD dwCertEncodingType,
(LPWSTR)&qualifier, 0);
if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
{
- headingSep = colonCrlf;
- sep = crlf;
+ headingSep = L":\r\n";
+ sep = L"\r\n";
}
else
{
- headingSep = colonSpace;
- sep = commaSep;
+ headingSep = L": ";
+ sep = L", ";
}
sepLen = lstrlenW(sep);
headingSepLen = lstrlenW(headingSep);
@@ -835,7 +819,7 @@ BOOL WINAPI FormatVerisignExtension(DWORD dwCertEncodingType,
charsNeeded += 1; /* '['*/
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
*str++ = '[';
- swprintf(policyNum, ARRAY_SIZE(policyNum), numFmt, i + 1);
+ swprintf(policyNum, ARRAY_SIZE(policyNum), L"%d", i + 1);
charsNeeded += lstrlenW(policyNum);
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
{
@@ -912,7 +896,7 @@ BOOL WINAPI FormatVerisignExtension(DWORD dwCertEncodingType,
charsNeeded += 1; /* ','*/
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
*str++ = ',';
- swprintf(policyQualifierNum, ARRAY_SIZE(policyQualifierNum), numFmt, j + 1);
+ swprintf(policyQualifierNum, ARRAY_SIZE(policyQualifierNum), L"%d", j + 1);
charsNeeded += lstrlenW(policyQualifierNum);
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
{
@@ -1120,22 +1104,13 @@ BOOL WINAPI FormatVerisignExtension(DWORD dwCertEncodingType,
*/
HRESULT WINAPI DllRegisterServer(void)
{
- static WCHAR cryptdlg[] = { 'c','r','y','p','t','d','l','g','.',
- 'd','l','l',0 };
- static WCHAR wintrust[] = { 'w','i','n','t','r','u','s','t','.',
- 'd','l','l',0 };
- static WCHAR certTrustInit[] = { 'C','e','r','t','T','r','u','s','t',
- 'I','n','i','t',0 };
- static WCHAR wintrustCertificateTrust[] = { 'W','i','n','t','r','u','s','t',
- 'C','e','r','t','i','f','i','c','a','t','e','T','r','u','s','t',0 };
- static WCHAR certTrustCertPolicy[] = { 'C','e','r','t','T','r','u','s','t',
- 'C','e','r','t','P','o','l','i','c','y',0 };
- static WCHAR certTrustFinalPolicy[] = { 'C','e','r','t','T','r','u','s','t',
- 'F','i','n','a','l','P','o','l','i','c','y',0 };
- static WCHAR certTrustCleanup[] = { 'C','e','r','t','T','r','u','s','t',
- 'C','l','e','a','n','u','p',0 };
- static const WCHAR cryptDlg[] = { 'c','r','y','p','t','d','l','g','.',
- 'd','l','l',0 };
+ static WCHAR cryptdlg[] = L"cryptdlg.dll";
+ static WCHAR wintrust[] = L"wintrust.dll";
+ static WCHAR certTrustInit[] = L"CertTrustInit";
+ static WCHAR wintrustCertificateTrust[] = L"WintrustCertificateTrust";
+ static WCHAR certTrustCertPolicy[] = L"CertTrustCertPolicy";
+ static WCHAR certTrustFinalPolicy[] = L"CertTrustFinalPolicy";
+ static WCHAR certTrustCleanup[] = L"CertTrustCleanup";
CRYPT_REGISTER_ACTIONID reg;
GUID guid = CERT_CERTIFICATE_ACTION_VERIFY;
HRESULT hr = S_OK;
@@ -1160,17 +1135,17 @@ HRESULT WINAPI DllRegisterServer(void)
if (!WintrustAddActionID(&guid, WT_ADD_ACTION_ID_RET_RESULT_FLAG, ®))
hr = GetLastError();
CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_ENCODE_OBJECT_FUNC,
- "1.3.6.1.4.1.311.16.1.1", cryptDlg, "EncodeAttrSequence");
+ "1.3.6.1.4.1.311.16.1.1", L"cryptdlg.dll", "EncodeAttrSequence");
CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_ENCODE_OBJECT_FUNC,
- szOID_MICROSOFT_Encryption_Key_Preference, cryptDlg, "EncodeRecipientID");
+ szOID_MICROSOFT_Encryption_Key_Preference, L"cryptdlg.dll", "EncodeRecipientID");
CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_DECODE_OBJECT_FUNC,
- "1.3.6.1.4.1.311.16.1.1", cryptDlg, "DecodeAttrSequence");
+ "1.3.6.1.4.1.311.16.1.1", L"cryptdlg.dll", "DecodeAttrSequence");
CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_DECODE_OBJECT_FUNC,
- szOID_MICROSOFT_Encryption_Key_Preference, cryptDlg, "DecodeRecipientID");
+ szOID_MICROSOFT_Encryption_Key_Preference, L"cryptdlg.dll", "DecodeRecipientID");
CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_FORMAT_OBJECT_FUNC,
- szOID_PKIX_KP_EMAIL_PROTECTION, cryptDlg, "FormatPKIXEmailProtection");
+ szOID_PKIX_KP_EMAIL_PROTECTION, L"cryptdlg.dll", "FormatPKIXEmailProtection");
CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_FORMAT_OBJECT_FUNC,
- szOID_CERT_POLICIES, cryptDlg, "FormatVerisignExtension");
+ szOID_CERT_POLICIES, L"cryptdlg.dll", "FormatVerisignExtension");
return hr;
}
--
2.26.2
1
0
[PATCH 1/4] winex11.drv: Do not set AA flags for font default AA in xrender backend.
by Paul Gofman 30 Nov '20
by Paul Gofman 30 Nov '20
30 Nov '20
If LOGFONT lfQuality assumes user default antialiasing Wine's
Control Panel\\Desktop parameters should be used.
Signed-off-by: Paul Gofman <pgofman(a)codeweavers.com>
---
dlls/winex11.drv/xrender.c | 11 -----------
1 file changed, 11 deletions(-)
diff --git a/dlls/winex11.drv/xrender.c b/dlls/winex11.drv/xrender.c
index 3376cee517d..bd42ced5105 100644
--- a/dlls/winex11.drv/xrender.c
+++ b/dlls/winex11.drv/xrender.c
@@ -795,17 +795,6 @@ static UINT get_xft_aa_flags( const LOGFONTW *lf )
case NONANTIALIASED_QUALITY:
case ANTIALIASED_QUALITY:
break;
- default:
- if (!(value = XGetDefault( gdi_display, "Xft", "antialias" ))) break;
- TRACE( "got antialias '%s'\n", value );
- if (tolower(value[0]) == 'f' || tolower(value[0]) == 'n' ||
- value[0] == '0' || !_strnicmp( value, "off", -1 ))
- {
- ret = GGO_BITMAP;
- break;
- }
- ret = GGO_GRAY4_BITMAP;
- /* fall through */
case CLEARTYPE_QUALITY:
case CLEARTYPE_NATURAL_QUALITY:
if (!(value = XGetDefault( gdi_display, "Xft", "rgba" ))) break;
--
2.28.0
2
7
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/dmband/dmobject.c | 111 +++++++++++++++++++++++++++++++++++++--
dlls/dmband/dmobject.h | 8 ++-
dlls/dmcompos/dmobject.c | 111 +++++++++++++++++++++++++++++++++++++--
dlls/dmcompos/dmobject.h | 8 ++-
dlls/dmloader/dmobject.c | 111 +++++++++++++++++++++++++++++++++++++--
dlls/dmloader/dmobject.h | 8 ++-
dlls/dmscript/dmobject.c | 111 +++++++++++++++++++++++++++++++++++++--
dlls/dmscript/dmobject.h | 8 ++-
dlls/dmstyle/dmobject.c | 111 +++++++++++++++++++++++++++++++++++++--
dlls/dmstyle/dmobject.h | 8 ++-
dlls/dmusic/dmobject.c | 111 +++++++++++++++++++++++++++++++++++++--
dlls/dmusic/dmobject.h | 8 ++-
dlls/dswave/dmobject.c | 111 +++++++++++++++++++++++++++++++++++++--
dlls/dswave/dmobject.h | 8 ++-
14 files changed, 791 insertions(+), 42 deletions(-)
diff --git a/dlls/dmband/dmobject.c b/dlls/dmband/dmobject.c
index 9ea31ab32a6..e6a1ce906a7 100644
--- a/dlls/dmband/dmobject.c
+++ b/dlls/dmband/dmobject.c
@@ -28,6 +28,7 @@
#include "dmusics.h"
#include "dmobject.h"
#include "wine/debug.h"
+#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL(dmobj);
WINE_DECLARE_DEBUG_CHANNEL(dmfile);
@@ -349,7 +350,7 @@ HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk)
return S_OK;
}
-HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk)
+HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk)
{
LARGE_INTEGER end;
@@ -371,6 +372,50 @@ HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk)
return stream_get_chunk(stream, chunk);
}
+/* Reads chunk data of the form:
+ DWORD - size of array element
+ element[] - Array of elements
+ The caller needs to heap_free() the array.
+*/
+HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
+ unsigned int *count, DWORD elem_size)
+{
+ DWORD size;
+ HRESULT hr;
+
+ *array = NULL;
+ *count = 0;
+
+ if (chunk->size < sizeof(DWORD)) {
+ WARN_(dmfile)("%s: Too short to read element size\n", debugstr_chunk(chunk));
+ return E_FAIL;
+ }
+ if (FAILED(hr = stream_read(stream, &size, sizeof(DWORD))))
+ return hr;
+ if (size != elem_size) {
+ WARN_(dmfile)("%s: Array element size mismatch: got %u, expected %u\n",
+ debugstr_chunk(chunk), size, elem_size);
+ return DMUS_E_UNSUPPORTED_STREAM;
+ }
+
+ *count = (chunk->size - sizeof(DWORD)) / elem_size;
+ size = *count * elem_size;
+ if (!(*array = heap_alloc(size)))
+ return E_OUTOFMEMORY;
+ if (FAILED(hr = stream_read(stream, *array, size))) {
+ heap_free(*array);
+ *array = NULL;
+ return hr;
+ }
+
+ if (chunk->size > size + sizeof(DWORD)) {
+ WARN_(dmfile)("%s: Extraneous data at end of array\n", debugstr_chunk(chunk));
+ stream_skip_chunk(stream, chunk);
+ return S_FALSE;
+ }
+ return S_OK;
+}
+
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
ULONG size)
{
@@ -529,15 +574,30 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) {
switch (chunk.id) {
+ case DMUS_FOURCC_CATEGORY_CHUNK:
+ if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
+ desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_CATEGORY;
+ break;
+ case DMUS_FOURCC_DATE_CHUNK:
+ if ((supported & DMUS_OBJ_DATE) && stream_chunk_get_data(stream, &chunk,
+ &desc->ftDate, sizeof(desc->ftDate)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_DATE;
+ break;
+ case DMUS_FOURCC_FILE_CHUNK:
+ if ((supported & DMUS_OBJ_FILENAME) && stream_chunk_get_wstr(stream, &chunk,
+ desc->wszFileName, sizeof(desc->wszFileName)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_FILENAME;
+ break;
case DMUS_FOURCC_GUID_CHUNK:
if ((supported & DMUS_OBJ_OBJECT) && stream_chunk_get_data(stream, &chunk,
&desc->guidObject, sizeof(desc->guidObject)) == S_OK)
desc->dwValidData |= DMUS_OBJ_OBJECT;
break;
- case DMUS_FOURCC_CATEGORY_CHUNK:
- if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
- desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
- desc->dwValidData |= DMUS_OBJ_CATEGORY;
+ case DMUS_FOURCC_NAME_CHUNK:
+ if ((supported & DMUS_OBJ_NAME) && stream_chunk_get_wstr(stream, &chunk,
+ desc->wszName, sizeof(desc->wszName)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_NAME;
break;
case DMUS_FOURCC_VERSION_CHUNK:
if ((supported & DMUS_OBJ_VERSION) && stream_chunk_get_data(stream, &chunk,
@@ -557,6 +617,47 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
return hr;
}
+HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
+ IDirectMusicObject **dmobj)
+{
+ struct chunk_entry chunk = {.parent = list};
+ IDirectMusicGetLoader *getloader;
+ IDirectMusicLoader *loader;
+ DMUS_OBJECTDESC desc;
+ DMUS_IO_REFERENCE reference;
+ HRESULT hr;
+
+ if (FAILED(hr = stream_next_chunk(stream, &chunk)))
+ return hr;
+ if (chunk.id != DMUS_FOURCC_REF_CHUNK)
+ return DMUS_E_UNSUPPORTED_STREAM;
+
+ if (FAILED(hr = stream_chunk_get_data(stream, &chunk, &reference, sizeof(reference)))) {
+ WARN("Failed to read data of %s\n", debugstr_chunk(&chunk));
+ return hr;
+ }
+ TRACE("REFERENCE guidClassID %s, dwValidData %#x\n", debugstr_dmguid(&reference.guidClassID),
+ reference.dwValidData);
+
+ if (FAILED(hr = dmobj_parsedescriptor(stream, list, &desc, reference.dwValidData)))
+ return hr;
+ desc.guidClass = reference.guidClassID;
+ desc.dwValidData |= DMUS_OBJ_CLASS;
+ dump_DMUS_OBJECTDESC(&desc);
+
+ if (FAILED(hr = IStream_QueryInterface(stream, &IID_IDirectMusicGetLoader, (void**)&getloader)))
+ return hr;
+ hr = IDirectMusicGetLoader_GetLoader(getloader, &loader);
+ IDirectMusicGetLoader_Release(getloader);
+ if (FAILED(hr))
+ return hr;
+
+ hr = IDirectMusicLoader_GetObject(loader, &desc, &IID_IDirectMusicObject, (void**)dmobj);
+ IDirectMusicLoader_Release(loader);
+
+ return hr;
+}
+
/* Generic IPersistStream methods */
static inline struct dmobject *impl_from_IPersistStream(IPersistStream *iface)
{
diff --git a/dlls/dmband/dmobject.h b/dlls/dmband/dmobject.h
index d347020691c..afe721dc824 100644
--- a/dlls/dmband/dmobject.h
+++ b/dlls/dmband/dmobject.h
@@ -33,8 +33,10 @@ struct chunk_entry {
HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
-HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
+HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk) DECLSPEC_HIDDEN;
+HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
+ unsigned int *count, DWORD elem_size) DECLSPEC_HIDDEN;
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
ULONG size) DECLSPEC_HIDDEN;
HRESULT stream_chunk_get_wstr(IStream *stream, const struct chunk_entry *chunk, WCHAR *str,
@@ -89,6 +91,10 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
#define DMUS_OBJ_NAME_INAM 0x1000 /* 'INAM' chunk in UNFO list */
#define DMUS_OBJ_NAME_INFO 0x2000 /* 'INAM' chunk in INFO list */
+/* 'DMRF' (reference list) helper */
+HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
+ IDirectMusicObject **dmobj) DECLSPEC_HIDDEN;
+
/* Generic IPersistStream methods */
HRESULT WINAPI dmobj_IPersistStream_QueryInterface(IPersistStream *iface, REFIID riid,
void **ret_iface) DECLSPEC_HIDDEN;
diff --git a/dlls/dmcompos/dmobject.c b/dlls/dmcompos/dmobject.c
index 9ea31ab32a6..e6a1ce906a7 100644
--- a/dlls/dmcompos/dmobject.c
+++ b/dlls/dmcompos/dmobject.c
@@ -28,6 +28,7 @@
#include "dmusics.h"
#include "dmobject.h"
#include "wine/debug.h"
+#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL(dmobj);
WINE_DECLARE_DEBUG_CHANNEL(dmfile);
@@ -349,7 +350,7 @@ HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk)
return S_OK;
}
-HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk)
+HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk)
{
LARGE_INTEGER end;
@@ -371,6 +372,50 @@ HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk)
return stream_get_chunk(stream, chunk);
}
+/* Reads chunk data of the form:
+ DWORD - size of array element
+ element[] - Array of elements
+ The caller needs to heap_free() the array.
+*/
+HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
+ unsigned int *count, DWORD elem_size)
+{
+ DWORD size;
+ HRESULT hr;
+
+ *array = NULL;
+ *count = 0;
+
+ if (chunk->size < sizeof(DWORD)) {
+ WARN_(dmfile)("%s: Too short to read element size\n", debugstr_chunk(chunk));
+ return E_FAIL;
+ }
+ if (FAILED(hr = stream_read(stream, &size, sizeof(DWORD))))
+ return hr;
+ if (size != elem_size) {
+ WARN_(dmfile)("%s: Array element size mismatch: got %u, expected %u\n",
+ debugstr_chunk(chunk), size, elem_size);
+ return DMUS_E_UNSUPPORTED_STREAM;
+ }
+
+ *count = (chunk->size - sizeof(DWORD)) / elem_size;
+ size = *count * elem_size;
+ if (!(*array = heap_alloc(size)))
+ return E_OUTOFMEMORY;
+ if (FAILED(hr = stream_read(stream, *array, size))) {
+ heap_free(*array);
+ *array = NULL;
+ return hr;
+ }
+
+ if (chunk->size > size + sizeof(DWORD)) {
+ WARN_(dmfile)("%s: Extraneous data at end of array\n", debugstr_chunk(chunk));
+ stream_skip_chunk(stream, chunk);
+ return S_FALSE;
+ }
+ return S_OK;
+}
+
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
ULONG size)
{
@@ -529,15 +574,30 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) {
switch (chunk.id) {
+ case DMUS_FOURCC_CATEGORY_CHUNK:
+ if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
+ desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_CATEGORY;
+ break;
+ case DMUS_FOURCC_DATE_CHUNK:
+ if ((supported & DMUS_OBJ_DATE) && stream_chunk_get_data(stream, &chunk,
+ &desc->ftDate, sizeof(desc->ftDate)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_DATE;
+ break;
+ case DMUS_FOURCC_FILE_CHUNK:
+ if ((supported & DMUS_OBJ_FILENAME) && stream_chunk_get_wstr(stream, &chunk,
+ desc->wszFileName, sizeof(desc->wszFileName)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_FILENAME;
+ break;
case DMUS_FOURCC_GUID_CHUNK:
if ((supported & DMUS_OBJ_OBJECT) && stream_chunk_get_data(stream, &chunk,
&desc->guidObject, sizeof(desc->guidObject)) == S_OK)
desc->dwValidData |= DMUS_OBJ_OBJECT;
break;
- case DMUS_FOURCC_CATEGORY_CHUNK:
- if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
- desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
- desc->dwValidData |= DMUS_OBJ_CATEGORY;
+ case DMUS_FOURCC_NAME_CHUNK:
+ if ((supported & DMUS_OBJ_NAME) && stream_chunk_get_wstr(stream, &chunk,
+ desc->wszName, sizeof(desc->wszName)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_NAME;
break;
case DMUS_FOURCC_VERSION_CHUNK:
if ((supported & DMUS_OBJ_VERSION) && stream_chunk_get_data(stream, &chunk,
@@ -557,6 +617,47 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
return hr;
}
+HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
+ IDirectMusicObject **dmobj)
+{
+ struct chunk_entry chunk = {.parent = list};
+ IDirectMusicGetLoader *getloader;
+ IDirectMusicLoader *loader;
+ DMUS_OBJECTDESC desc;
+ DMUS_IO_REFERENCE reference;
+ HRESULT hr;
+
+ if (FAILED(hr = stream_next_chunk(stream, &chunk)))
+ return hr;
+ if (chunk.id != DMUS_FOURCC_REF_CHUNK)
+ return DMUS_E_UNSUPPORTED_STREAM;
+
+ if (FAILED(hr = stream_chunk_get_data(stream, &chunk, &reference, sizeof(reference)))) {
+ WARN("Failed to read data of %s\n", debugstr_chunk(&chunk));
+ return hr;
+ }
+ TRACE("REFERENCE guidClassID %s, dwValidData %#x\n", debugstr_dmguid(&reference.guidClassID),
+ reference.dwValidData);
+
+ if (FAILED(hr = dmobj_parsedescriptor(stream, list, &desc, reference.dwValidData)))
+ return hr;
+ desc.guidClass = reference.guidClassID;
+ desc.dwValidData |= DMUS_OBJ_CLASS;
+ dump_DMUS_OBJECTDESC(&desc);
+
+ if (FAILED(hr = IStream_QueryInterface(stream, &IID_IDirectMusicGetLoader, (void**)&getloader)))
+ return hr;
+ hr = IDirectMusicGetLoader_GetLoader(getloader, &loader);
+ IDirectMusicGetLoader_Release(getloader);
+ if (FAILED(hr))
+ return hr;
+
+ hr = IDirectMusicLoader_GetObject(loader, &desc, &IID_IDirectMusicObject, (void**)dmobj);
+ IDirectMusicLoader_Release(loader);
+
+ return hr;
+}
+
/* Generic IPersistStream methods */
static inline struct dmobject *impl_from_IPersistStream(IPersistStream *iface)
{
diff --git a/dlls/dmcompos/dmobject.h b/dlls/dmcompos/dmobject.h
index d347020691c..afe721dc824 100644
--- a/dlls/dmcompos/dmobject.h
+++ b/dlls/dmcompos/dmobject.h
@@ -33,8 +33,10 @@ struct chunk_entry {
HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
-HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
+HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk) DECLSPEC_HIDDEN;
+HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
+ unsigned int *count, DWORD elem_size) DECLSPEC_HIDDEN;
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
ULONG size) DECLSPEC_HIDDEN;
HRESULT stream_chunk_get_wstr(IStream *stream, const struct chunk_entry *chunk, WCHAR *str,
@@ -89,6 +91,10 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
#define DMUS_OBJ_NAME_INAM 0x1000 /* 'INAM' chunk in UNFO list */
#define DMUS_OBJ_NAME_INFO 0x2000 /* 'INAM' chunk in INFO list */
+/* 'DMRF' (reference list) helper */
+HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
+ IDirectMusicObject **dmobj) DECLSPEC_HIDDEN;
+
/* Generic IPersistStream methods */
HRESULT WINAPI dmobj_IPersistStream_QueryInterface(IPersistStream *iface, REFIID riid,
void **ret_iface) DECLSPEC_HIDDEN;
diff --git a/dlls/dmloader/dmobject.c b/dlls/dmloader/dmobject.c
index 9ea31ab32a6..e6a1ce906a7 100644
--- a/dlls/dmloader/dmobject.c
+++ b/dlls/dmloader/dmobject.c
@@ -28,6 +28,7 @@
#include "dmusics.h"
#include "dmobject.h"
#include "wine/debug.h"
+#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL(dmobj);
WINE_DECLARE_DEBUG_CHANNEL(dmfile);
@@ -349,7 +350,7 @@ HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk)
return S_OK;
}
-HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk)
+HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk)
{
LARGE_INTEGER end;
@@ -371,6 +372,50 @@ HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk)
return stream_get_chunk(stream, chunk);
}
+/* Reads chunk data of the form:
+ DWORD - size of array element
+ element[] - Array of elements
+ The caller needs to heap_free() the array.
+*/
+HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
+ unsigned int *count, DWORD elem_size)
+{
+ DWORD size;
+ HRESULT hr;
+
+ *array = NULL;
+ *count = 0;
+
+ if (chunk->size < sizeof(DWORD)) {
+ WARN_(dmfile)("%s: Too short to read element size\n", debugstr_chunk(chunk));
+ return E_FAIL;
+ }
+ if (FAILED(hr = stream_read(stream, &size, sizeof(DWORD))))
+ return hr;
+ if (size != elem_size) {
+ WARN_(dmfile)("%s: Array element size mismatch: got %u, expected %u\n",
+ debugstr_chunk(chunk), size, elem_size);
+ return DMUS_E_UNSUPPORTED_STREAM;
+ }
+
+ *count = (chunk->size - sizeof(DWORD)) / elem_size;
+ size = *count * elem_size;
+ if (!(*array = heap_alloc(size)))
+ return E_OUTOFMEMORY;
+ if (FAILED(hr = stream_read(stream, *array, size))) {
+ heap_free(*array);
+ *array = NULL;
+ return hr;
+ }
+
+ if (chunk->size > size + sizeof(DWORD)) {
+ WARN_(dmfile)("%s: Extraneous data at end of array\n", debugstr_chunk(chunk));
+ stream_skip_chunk(stream, chunk);
+ return S_FALSE;
+ }
+ return S_OK;
+}
+
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
ULONG size)
{
@@ -529,15 +574,30 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) {
switch (chunk.id) {
+ case DMUS_FOURCC_CATEGORY_CHUNK:
+ if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
+ desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_CATEGORY;
+ break;
+ case DMUS_FOURCC_DATE_CHUNK:
+ if ((supported & DMUS_OBJ_DATE) && stream_chunk_get_data(stream, &chunk,
+ &desc->ftDate, sizeof(desc->ftDate)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_DATE;
+ break;
+ case DMUS_FOURCC_FILE_CHUNK:
+ if ((supported & DMUS_OBJ_FILENAME) && stream_chunk_get_wstr(stream, &chunk,
+ desc->wszFileName, sizeof(desc->wszFileName)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_FILENAME;
+ break;
case DMUS_FOURCC_GUID_CHUNK:
if ((supported & DMUS_OBJ_OBJECT) && stream_chunk_get_data(stream, &chunk,
&desc->guidObject, sizeof(desc->guidObject)) == S_OK)
desc->dwValidData |= DMUS_OBJ_OBJECT;
break;
- case DMUS_FOURCC_CATEGORY_CHUNK:
- if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
- desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
- desc->dwValidData |= DMUS_OBJ_CATEGORY;
+ case DMUS_FOURCC_NAME_CHUNK:
+ if ((supported & DMUS_OBJ_NAME) && stream_chunk_get_wstr(stream, &chunk,
+ desc->wszName, sizeof(desc->wszName)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_NAME;
break;
case DMUS_FOURCC_VERSION_CHUNK:
if ((supported & DMUS_OBJ_VERSION) && stream_chunk_get_data(stream, &chunk,
@@ -557,6 +617,47 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
return hr;
}
+HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
+ IDirectMusicObject **dmobj)
+{
+ struct chunk_entry chunk = {.parent = list};
+ IDirectMusicGetLoader *getloader;
+ IDirectMusicLoader *loader;
+ DMUS_OBJECTDESC desc;
+ DMUS_IO_REFERENCE reference;
+ HRESULT hr;
+
+ if (FAILED(hr = stream_next_chunk(stream, &chunk)))
+ return hr;
+ if (chunk.id != DMUS_FOURCC_REF_CHUNK)
+ return DMUS_E_UNSUPPORTED_STREAM;
+
+ if (FAILED(hr = stream_chunk_get_data(stream, &chunk, &reference, sizeof(reference)))) {
+ WARN("Failed to read data of %s\n", debugstr_chunk(&chunk));
+ return hr;
+ }
+ TRACE("REFERENCE guidClassID %s, dwValidData %#x\n", debugstr_dmguid(&reference.guidClassID),
+ reference.dwValidData);
+
+ if (FAILED(hr = dmobj_parsedescriptor(stream, list, &desc, reference.dwValidData)))
+ return hr;
+ desc.guidClass = reference.guidClassID;
+ desc.dwValidData |= DMUS_OBJ_CLASS;
+ dump_DMUS_OBJECTDESC(&desc);
+
+ if (FAILED(hr = IStream_QueryInterface(stream, &IID_IDirectMusicGetLoader, (void**)&getloader)))
+ return hr;
+ hr = IDirectMusicGetLoader_GetLoader(getloader, &loader);
+ IDirectMusicGetLoader_Release(getloader);
+ if (FAILED(hr))
+ return hr;
+
+ hr = IDirectMusicLoader_GetObject(loader, &desc, &IID_IDirectMusicObject, (void**)dmobj);
+ IDirectMusicLoader_Release(loader);
+
+ return hr;
+}
+
/* Generic IPersistStream methods */
static inline struct dmobject *impl_from_IPersistStream(IPersistStream *iface)
{
diff --git a/dlls/dmloader/dmobject.h b/dlls/dmloader/dmobject.h
index d347020691c..afe721dc824 100644
--- a/dlls/dmloader/dmobject.h
+++ b/dlls/dmloader/dmobject.h
@@ -33,8 +33,10 @@ struct chunk_entry {
HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
-HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
+HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk) DECLSPEC_HIDDEN;
+HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
+ unsigned int *count, DWORD elem_size) DECLSPEC_HIDDEN;
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
ULONG size) DECLSPEC_HIDDEN;
HRESULT stream_chunk_get_wstr(IStream *stream, const struct chunk_entry *chunk, WCHAR *str,
@@ -89,6 +91,10 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
#define DMUS_OBJ_NAME_INAM 0x1000 /* 'INAM' chunk in UNFO list */
#define DMUS_OBJ_NAME_INFO 0x2000 /* 'INAM' chunk in INFO list */
+/* 'DMRF' (reference list) helper */
+HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
+ IDirectMusicObject **dmobj) DECLSPEC_HIDDEN;
+
/* Generic IPersistStream methods */
HRESULT WINAPI dmobj_IPersistStream_QueryInterface(IPersistStream *iface, REFIID riid,
void **ret_iface) DECLSPEC_HIDDEN;
diff --git a/dlls/dmscript/dmobject.c b/dlls/dmscript/dmobject.c
index 9ea31ab32a6..e6a1ce906a7 100644
--- a/dlls/dmscript/dmobject.c
+++ b/dlls/dmscript/dmobject.c
@@ -28,6 +28,7 @@
#include "dmusics.h"
#include "dmobject.h"
#include "wine/debug.h"
+#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL(dmobj);
WINE_DECLARE_DEBUG_CHANNEL(dmfile);
@@ -349,7 +350,7 @@ HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk)
return S_OK;
}
-HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk)
+HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk)
{
LARGE_INTEGER end;
@@ -371,6 +372,50 @@ HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk)
return stream_get_chunk(stream, chunk);
}
+/* Reads chunk data of the form:
+ DWORD - size of array element
+ element[] - Array of elements
+ The caller needs to heap_free() the array.
+*/
+HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
+ unsigned int *count, DWORD elem_size)
+{
+ DWORD size;
+ HRESULT hr;
+
+ *array = NULL;
+ *count = 0;
+
+ if (chunk->size < sizeof(DWORD)) {
+ WARN_(dmfile)("%s: Too short to read element size\n", debugstr_chunk(chunk));
+ return E_FAIL;
+ }
+ if (FAILED(hr = stream_read(stream, &size, sizeof(DWORD))))
+ return hr;
+ if (size != elem_size) {
+ WARN_(dmfile)("%s: Array element size mismatch: got %u, expected %u\n",
+ debugstr_chunk(chunk), size, elem_size);
+ return DMUS_E_UNSUPPORTED_STREAM;
+ }
+
+ *count = (chunk->size - sizeof(DWORD)) / elem_size;
+ size = *count * elem_size;
+ if (!(*array = heap_alloc(size)))
+ return E_OUTOFMEMORY;
+ if (FAILED(hr = stream_read(stream, *array, size))) {
+ heap_free(*array);
+ *array = NULL;
+ return hr;
+ }
+
+ if (chunk->size > size + sizeof(DWORD)) {
+ WARN_(dmfile)("%s: Extraneous data at end of array\n", debugstr_chunk(chunk));
+ stream_skip_chunk(stream, chunk);
+ return S_FALSE;
+ }
+ return S_OK;
+}
+
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
ULONG size)
{
@@ -529,15 +574,30 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) {
switch (chunk.id) {
+ case DMUS_FOURCC_CATEGORY_CHUNK:
+ if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
+ desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_CATEGORY;
+ break;
+ case DMUS_FOURCC_DATE_CHUNK:
+ if ((supported & DMUS_OBJ_DATE) && stream_chunk_get_data(stream, &chunk,
+ &desc->ftDate, sizeof(desc->ftDate)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_DATE;
+ break;
+ case DMUS_FOURCC_FILE_CHUNK:
+ if ((supported & DMUS_OBJ_FILENAME) && stream_chunk_get_wstr(stream, &chunk,
+ desc->wszFileName, sizeof(desc->wszFileName)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_FILENAME;
+ break;
case DMUS_FOURCC_GUID_CHUNK:
if ((supported & DMUS_OBJ_OBJECT) && stream_chunk_get_data(stream, &chunk,
&desc->guidObject, sizeof(desc->guidObject)) == S_OK)
desc->dwValidData |= DMUS_OBJ_OBJECT;
break;
- case DMUS_FOURCC_CATEGORY_CHUNK:
- if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
- desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
- desc->dwValidData |= DMUS_OBJ_CATEGORY;
+ case DMUS_FOURCC_NAME_CHUNK:
+ if ((supported & DMUS_OBJ_NAME) && stream_chunk_get_wstr(stream, &chunk,
+ desc->wszName, sizeof(desc->wszName)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_NAME;
break;
case DMUS_FOURCC_VERSION_CHUNK:
if ((supported & DMUS_OBJ_VERSION) && stream_chunk_get_data(stream, &chunk,
@@ -557,6 +617,47 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
return hr;
}
+HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
+ IDirectMusicObject **dmobj)
+{
+ struct chunk_entry chunk = {.parent = list};
+ IDirectMusicGetLoader *getloader;
+ IDirectMusicLoader *loader;
+ DMUS_OBJECTDESC desc;
+ DMUS_IO_REFERENCE reference;
+ HRESULT hr;
+
+ if (FAILED(hr = stream_next_chunk(stream, &chunk)))
+ return hr;
+ if (chunk.id != DMUS_FOURCC_REF_CHUNK)
+ return DMUS_E_UNSUPPORTED_STREAM;
+
+ if (FAILED(hr = stream_chunk_get_data(stream, &chunk, &reference, sizeof(reference)))) {
+ WARN("Failed to read data of %s\n", debugstr_chunk(&chunk));
+ return hr;
+ }
+ TRACE("REFERENCE guidClassID %s, dwValidData %#x\n", debugstr_dmguid(&reference.guidClassID),
+ reference.dwValidData);
+
+ if (FAILED(hr = dmobj_parsedescriptor(stream, list, &desc, reference.dwValidData)))
+ return hr;
+ desc.guidClass = reference.guidClassID;
+ desc.dwValidData |= DMUS_OBJ_CLASS;
+ dump_DMUS_OBJECTDESC(&desc);
+
+ if (FAILED(hr = IStream_QueryInterface(stream, &IID_IDirectMusicGetLoader, (void**)&getloader)))
+ return hr;
+ hr = IDirectMusicGetLoader_GetLoader(getloader, &loader);
+ IDirectMusicGetLoader_Release(getloader);
+ if (FAILED(hr))
+ return hr;
+
+ hr = IDirectMusicLoader_GetObject(loader, &desc, &IID_IDirectMusicObject, (void**)dmobj);
+ IDirectMusicLoader_Release(loader);
+
+ return hr;
+}
+
/* Generic IPersistStream methods */
static inline struct dmobject *impl_from_IPersistStream(IPersistStream *iface)
{
diff --git a/dlls/dmscript/dmobject.h b/dlls/dmscript/dmobject.h
index d347020691c..afe721dc824 100644
--- a/dlls/dmscript/dmobject.h
+++ b/dlls/dmscript/dmobject.h
@@ -33,8 +33,10 @@ struct chunk_entry {
HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
-HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
+HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk) DECLSPEC_HIDDEN;
+HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
+ unsigned int *count, DWORD elem_size) DECLSPEC_HIDDEN;
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
ULONG size) DECLSPEC_HIDDEN;
HRESULT stream_chunk_get_wstr(IStream *stream, const struct chunk_entry *chunk, WCHAR *str,
@@ -89,6 +91,10 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
#define DMUS_OBJ_NAME_INAM 0x1000 /* 'INAM' chunk in UNFO list */
#define DMUS_OBJ_NAME_INFO 0x2000 /* 'INAM' chunk in INFO list */
+/* 'DMRF' (reference list) helper */
+HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
+ IDirectMusicObject **dmobj) DECLSPEC_HIDDEN;
+
/* Generic IPersistStream methods */
HRESULT WINAPI dmobj_IPersistStream_QueryInterface(IPersistStream *iface, REFIID riid,
void **ret_iface) DECLSPEC_HIDDEN;
diff --git a/dlls/dmstyle/dmobject.c b/dlls/dmstyle/dmobject.c
index 9ea31ab32a6..e6a1ce906a7 100644
--- a/dlls/dmstyle/dmobject.c
+++ b/dlls/dmstyle/dmobject.c
@@ -28,6 +28,7 @@
#include "dmusics.h"
#include "dmobject.h"
#include "wine/debug.h"
+#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL(dmobj);
WINE_DECLARE_DEBUG_CHANNEL(dmfile);
@@ -349,7 +350,7 @@ HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk)
return S_OK;
}
-HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk)
+HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk)
{
LARGE_INTEGER end;
@@ -371,6 +372,50 @@ HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk)
return stream_get_chunk(stream, chunk);
}
+/* Reads chunk data of the form:
+ DWORD - size of array element
+ element[] - Array of elements
+ The caller needs to heap_free() the array.
+*/
+HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
+ unsigned int *count, DWORD elem_size)
+{
+ DWORD size;
+ HRESULT hr;
+
+ *array = NULL;
+ *count = 0;
+
+ if (chunk->size < sizeof(DWORD)) {
+ WARN_(dmfile)("%s: Too short to read element size\n", debugstr_chunk(chunk));
+ return E_FAIL;
+ }
+ if (FAILED(hr = stream_read(stream, &size, sizeof(DWORD))))
+ return hr;
+ if (size != elem_size) {
+ WARN_(dmfile)("%s: Array element size mismatch: got %u, expected %u\n",
+ debugstr_chunk(chunk), size, elem_size);
+ return DMUS_E_UNSUPPORTED_STREAM;
+ }
+
+ *count = (chunk->size - sizeof(DWORD)) / elem_size;
+ size = *count * elem_size;
+ if (!(*array = heap_alloc(size)))
+ return E_OUTOFMEMORY;
+ if (FAILED(hr = stream_read(stream, *array, size))) {
+ heap_free(*array);
+ *array = NULL;
+ return hr;
+ }
+
+ if (chunk->size > size + sizeof(DWORD)) {
+ WARN_(dmfile)("%s: Extraneous data at end of array\n", debugstr_chunk(chunk));
+ stream_skip_chunk(stream, chunk);
+ return S_FALSE;
+ }
+ return S_OK;
+}
+
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
ULONG size)
{
@@ -529,15 +574,30 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) {
switch (chunk.id) {
+ case DMUS_FOURCC_CATEGORY_CHUNK:
+ if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
+ desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_CATEGORY;
+ break;
+ case DMUS_FOURCC_DATE_CHUNK:
+ if ((supported & DMUS_OBJ_DATE) && stream_chunk_get_data(stream, &chunk,
+ &desc->ftDate, sizeof(desc->ftDate)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_DATE;
+ break;
+ case DMUS_FOURCC_FILE_CHUNK:
+ if ((supported & DMUS_OBJ_FILENAME) && stream_chunk_get_wstr(stream, &chunk,
+ desc->wszFileName, sizeof(desc->wszFileName)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_FILENAME;
+ break;
case DMUS_FOURCC_GUID_CHUNK:
if ((supported & DMUS_OBJ_OBJECT) && stream_chunk_get_data(stream, &chunk,
&desc->guidObject, sizeof(desc->guidObject)) == S_OK)
desc->dwValidData |= DMUS_OBJ_OBJECT;
break;
- case DMUS_FOURCC_CATEGORY_CHUNK:
- if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
- desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
- desc->dwValidData |= DMUS_OBJ_CATEGORY;
+ case DMUS_FOURCC_NAME_CHUNK:
+ if ((supported & DMUS_OBJ_NAME) && stream_chunk_get_wstr(stream, &chunk,
+ desc->wszName, sizeof(desc->wszName)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_NAME;
break;
case DMUS_FOURCC_VERSION_CHUNK:
if ((supported & DMUS_OBJ_VERSION) && stream_chunk_get_data(stream, &chunk,
@@ -557,6 +617,47 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
return hr;
}
+HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
+ IDirectMusicObject **dmobj)
+{
+ struct chunk_entry chunk = {.parent = list};
+ IDirectMusicGetLoader *getloader;
+ IDirectMusicLoader *loader;
+ DMUS_OBJECTDESC desc;
+ DMUS_IO_REFERENCE reference;
+ HRESULT hr;
+
+ if (FAILED(hr = stream_next_chunk(stream, &chunk)))
+ return hr;
+ if (chunk.id != DMUS_FOURCC_REF_CHUNK)
+ return DMUS_E_UNSUPPORTED_STREAM;
+
+ if (FAILED(hr = stream_chunk_get_data(stream, &chunk, &reference, sizeof(reference)))) {
+ WARN("Failed to read data of %s\n", debugstr_chunk(&chunk));
+ return hr;
+ }
+ TRACE("REFERENCE guidClassID %s, dwValidData %#x\n", debugstr_dmguid(&reference.guidClassID),
+ reference.dwValidData);
+
+ if (FAILED(hr = dmobj_parsedescriptor(stream, list, &desc, reference.dwValidData)))
+ return hr;
+ desc.guidClass = reference.guidClassID;
+ desc.dwValidData |= DMUS_OBJ_CLASS;
+ dump_DMUS_OBJECTDESC(&desc);
+
+ if (FAILED(hr = IStream_QueryInterface(stream, &IID_IDirectMusicGetLoader, (void**)&getloader)))
+ return hr;
+ hr = IDirectMusicGetLoader_GetLoader(getloader, &loader);
+ IDirectMusicGetLoader_Release(getloader);
+ if (FAILED(hr))
+ return hr;
+
+ hr = IDirectMusicLoader_GetObject(loader, &desc, &IID_IDirectMusicObject, (void**)dmobj);
+ IDirectMusicLoader_Release(loader);
+
+ return hr;
+}
+
/* Generic IPersistStream methods */
static inline struct dmobject *impl_from_IPersistStream(IPersistStream *iface)
{
diff --git a/dlls/dmstyle/dmobject.h b/dlls/dmstyle/dmobject.h
index d347020691c..afe721dc824 100644
--- a/dlls/dmstyle/dmobject.h
+++ b/dlls/dmstyle/dmobject.h
@@ -33,8 +33,10 @@ struct chunk_entry {
HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
-HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
+HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk) DECLSPEC_HIDDEN;
+HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
+ unsigned int *count, DWORD elem_size) DECLSPEC_HIDDEN;
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
ULONG size) DECLSPEC_HIDDEN;
HRESULT stream_chunk_get_wstr(IStream *stream, const struct chunk_entry *chunk, WCHAR *str,
@@ -89,6 +91,10 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
#define DMUS_OBJ_NAME_INAM 0x1000 /* 'INAM' chunk in UNFO list */
#define DMUS_OBJ_NAME_INFO 0x2000 /* 'INAM' chunk in INFO list */
+/* 'DMRF' (reference list) helper */
+HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
+ IDirectMusicObject **dmobj) DECLSPEC_HIDDEN;
+
/* Generic IPersistStream methods */
HRESULT WINAPI dmobj_IPersistStream_QueryInterface(IPersistStream *iface, REFIID riid,
void **ret_iface) DECLSPEC_HIDDEN;
diff --git a/dlls/dmusic/dmobject.c b/dlls/dmusic/dmobject.c
index 9ea31ab32a6..e6a1ce906a7 100644
--- a/dlls/dmusic/dmobject.c
+++ b/dlls/dmusic/dmobject.c
@@ -28,6 +28,7 @@
#include "dmusics.h"
#include "dmobject.h"
#include "wine/debug.h"
+#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL(dmobj);
WINE_DECLARE_DEBUG_CHANNEL(dmfile);
@@ -349,7 +350,7 @@ HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk)
return S_OK;
}
-HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk)
+HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk)
{
LARGE_INTEGER end;
@@ -371,6 +372,50 @@ HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk)
return stream_get_chunk(stream, chunk);
}
+/* Reads chunk data of the form:
+ DWORD - size of array element
+ element[] - Array of elements
+ The caller needs to heap_free() the array.
+*/
+HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
+ unsigned int *count, DWORD elem_size)
+{
+ DWORD size;
+ HRESULT hr;
+
+ *array = NULL;
+ *count = 0;
+
+ if (chunk->size < sizeof(DWORD)) {
+ WARN_(dmfile)("%s: Too short to read element size\n", debugstr_chunk(chunk));
+ return E_FAIL;
+ }
+ if (FAILED(hr = stream_read(stream, &size, sizeof(DWORD))))
+ return hr;
+ if (size != elem_size) {
+ WARN_(dmfile)("%s: Array element size mismatch: got %u, expected %u\n",
+ debugstr_chunk(chunk), size, elem_size);
+ return DMUS_E_UNSUPPORTED_STREAM;
+ }
+
+ *count = (chunk->size - sizeof(DWORD)) / elem_size;
+ size = *count * elem_size;
+ if (!(*array = heap_alloc(size)))
+ return E_OUTOFMEMORY;
+ if (FAILED(hr = stream_read(stream, *array, size))) {
+ heap_free(*array);
+ *array = NULL;
+ return hr;
+ }
+
+ if (chunk->size > size + sizeof(DWORD)) {
+ WARN_(dmfile)("%s: Extraneous data at end of array\n", debugstr_chunk(chunk));
+ stream_skip_chunk(stream, chunk);
+ return S_FALSE;
+ }
+ return S_OK;
+}
+
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
ULONG size)
{
@@ -529,15 +574,30 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) {
switch (chunk.id) {
+ case DMUS_FOURCC_CATEGORY_CHUNK:
+ if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
+ desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_CATEGORY;
+ break;
+ case DMUS_FOURCC_DATE_CHUNK:
+ if ((supported & DMUS_OBJ_DATE) && stream_chunk_get_data(stream, &chunk,
+ &desc->ftDate, sizeof(desc->ftDate)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_DATE;
+ break;
+ case DMUS_FOURCC_FILE_CHUNK:
+ if ((supported & DMUS_OBJ_FILENAME) && stream_chunk_get_wstr(stream, &chunk,
+ desc->wszFileName, sizeof(desc->wszFileName)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_FILENAME;
+ break;
case DMUS_FOURCC_GUID_CHUNK:
if ((supported & DMUS_OBJ_OBJECT) && stream_chunk_get_data(stream, &chunk,
&desc->guidObject, sizeof(desc->guidObject)) == S_OK)
desc->dwValidData |= DMUS_OBJ_OBJECT;
break;
- case DMUS_FOURCC_CATEGORY_CHUNK:
- if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
- desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
- desc->dwValidData |= DMUS_OBJ_CATEGORY;
+ case DMUS_FOURCC_NAME_CHUNK:
+ if ((supported & DMUS_OBJ_NAME) && stream_chunk_get_wstr(stream, &chunk,
+ desc->wszName, sizeof(desc->wszName)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_NAME;
break;
case DMUS_FOURCC_VERSION_CHUNK:
if ((supported & DMUS_OBJ_VERSION) && stream_chunk_get_data(stream, &chunk,
@@ -557,6 +617,47 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
return hr;
}
+HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
+ IDirectMusicObject **dmobj)
+{
+ struct chunk_entry chunk = {.parent = list};
+ IDirectMusicGetLoader *getloader;
+ IDirectMusicLoader *loader;
+ DMUS_OBJECTDESC desc;
+ DMUS_IO_REFERENCE reference;
+ HRESULT hr;
+
+ if (FAILED(hr = stream_next_chunk(stream, &chunk)))
+ return hr;
+ if (chunk.id != DMUS_FOURCC_REF_CHUNK)
+ return DMUS_E_UNSUPPORTED_STREAM;
+
+ if (FAILED(hr = stream_chunk_get_data(stream, &chunk, &reference, sizeof(reference)))) {
+ WARN("Failed to read data of %s\n", debugstr_chunk(&chunk));
+ return hr;
+ }
+ TRACE("REFERENCE guidClassID %s, dwValidData %#x\n", debugstr_dmguid(&reference.guidClassID),
+ reference.dwValidData);
+
+ if (FAILED(hr = dmobj_parsedescriptor(stream, list, &desc, reference.dwValidData)))
+ return hr;
+ desc.guidClass = reference.guidClassID;
+ desc.dwValidData |= DMUS_OBJ_CLASS;
+ dump_DMUS_OBJECTDESC(&desc);
+
+ if (FAILED(hr = IStream_QueryInterface(stream, &IID_IDirectMusicGetLoader, (void**)&getloader)))
+ return hr;
+ hr = IDirectMusicGetLoader_GetLoader(getloader, &loader);
+ IDirectMusicGetLoader_Release(getloader);
+ if (FAILED(hr))
+ return hr;
+
+ hr = IDirectMusicLoader_GetObject(loader, &desc, &IID_IDirectMusicObject, (void**)dmobj);
+ IDirectMusicLoader_Release(loader);
+
+ return hr;
+}
+
/* Generic IPersistStream methods */
static inline struct dmobject *impl_from_IPersistStream(IPersistStream *iface)
{
diff --git a/dlls/dmusic/dmobject.h b/dlls/dmusic/dmobject.h
index d347020691c..afe721dc824 100644
--- a/dlls/dmusic/dmobject.h
+++ b/dlls/dmusic/dmobject.h
@@ -33,8 +33,10 @@ struct chunk_entry {
HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
-HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
+HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk) DECLSPEC_HIDDEN;
+HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
+ unsigned int *count, DWORD elem_size) DECLSPEC_HIDDEN;
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
ULONG size) DECLSPEC_HIDDEN;
HRESULT stream_chunk_get_wstr(IStream *stream, const struct chunk_entry *chunk, WCHAR *str,
@@ -89,6 +91,10 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
#define DMUS_OBJ_NAME_INAM 0x1000 /* 'INAM' chunk in UNFO list */
#define DMUS_OBJ_NAME_INFO 0x2000 /* 'INAM' chunk in INFO list */
+/* 'DMRF' (reference list) helper */
+HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
+ IDirectMusicObject **dmobj) DECLSPEC_HIDDEN;
+
/* Generic IPersistStream methods */
HRESULT WINAPI dmobj_IPersistStream_QueryInterface(IPersistStream *iface, REFIID riid,
void **ret_iface) DECLSPEC_HIDDEN;
diff --git a/dlls/dswave/dmobject.c b/dlls/dswave/dmobject.c
index 9ea31ab32a6..e6a1ce906a7 100644
--- a/dlls/dswave/dmobject.c
+++ b/dlls/dswave/dmobject.c
@@ -28,6 +28,7 @@
#include "dmusics.h"
#include "dmobject.h"
#include "wine/debug.h"
+#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL(dmobj);
WINE_DECLARE_DEBUG_CHANNEL(dmfile);
@@ -349,7 +350,7 @@ HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk)
return S_OK;
}
-HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk)
+HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk)
{
LARGE_INTEGER end;
@@ -371,6 +372,50 @@ HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk)
return stream_get_chunk(stream, chunk);
}
+/* Reads chunk data of the form:
+ DWORD - size of array element
+ element[] - Array of elements
+ The caller needs to heap_free() the array.
+*/
+HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
+ unsigned int *count, DWORD elem_size)
+{
+ DWORD size;
+ HRESULT hr;
+
+ *array = NULL;
+ *count = 0;
+
+ if (chunk->size < sizeof(DWORD)) {
+ WARN_(dmfile)("%s: Too short to read element size\n", debugstr_chunk(chunk));
+ return E_FAIL;
+ }
+ if (FAILED(hr = stream_read(stream, &size, sizeof(DWORD))))
+ return hr;
+ if (size != elem_size) {
+ WARN_(dmfile)("%s: Array element size mismatch: got %u, expected %u\n",
+ debugstr_chunk(chunk), size, elem_size);
+ return DMUS_E_UNSUPPORTED_STREAM;
+ }
+
+ *count = (chunk->size - sizeof(DWORD)) / elem_size;
+ size = *count * elem_size;
+ if (!(*array = heap_alloc(size)))
+ return E_OUTOFMEMORY;
+ if (FAILED(hr = stream_read(stream, *array, size))) {
+ heap_free(*array);
+ *array = NULL;
+ return hr;
+ }
+
+ if (chunk->size > size + sizeof(DWORD)) {
+ WARN_(dmfile)("%s: Extraneous data at end of array\n", debugstr_chunk(chunk));
+ stream_skip_chunk(stream, chunk);
+ return S_FALSE;
+ }
+ return S_OK;
+}
+
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
ULONG size)
{
@@ -529,15 +574,30 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) {
switch (chunk.id) {
+ case DMUS_FOURCC_CATEGORY_CHUNK:
+ if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
+ desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_CATEGORY;
+ break;
+ case DMUS_FOURCC_DATE_CHUNK:
+ if ((supported & DMUS_OBJ_DATE) && stream_chunk_get_data(stream, &chunk,
+ &desc->ftDate, sizeof(desc->ftDate)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_DATE;
+ break;
+ case DMUS_FOURCC_FILE_CHUNK:
+ if ((supported & DMUS_OBJ_FILENAME) && stream_chunk_get_wstr(stream, &chunk,
+ desc->wszFileName, sizeof(desc->wszFileName)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_FILENAME;
+ break;
case DMUS_FOURCC_GUID_CHUNK:
if ((supported & DMUS_OBJ_OBJECT) && stream_chunk_get_data(stream, &chunk,
&desc->guidObject, sizeof(desc->guidObject)) == S_OK)
desc->dwValidData |= DMUS_OBJ_OBJECT;
break;
- case DMUS_FOURCC_CATEGORY_CHUNK:
- if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk,
- desc->wszCategory, sizeof(desc->wszCategory)) == S_OK)
- desc->dwValidData |= DMUS_OBJ_CATEGORY;
+ case DMUS_FOURCC_NAME_CHUNK:
+ if ((supported & DMUS_OBJ_NAME) && stream_chunk_get_wstr(stream, &chunk,
+ desc->wszName, sizeof(desc->wszName)) == S_OK)
+ desc->dwValidData |= DMUS_OBJ_NAME;
break;
case DMUS_FOURCC_VERSION_CHUNK:
if ((supported & DMUS_OBJ_VERSION) && stream_chunk_get_data(stream, &chunk,
@@ -557,6 +617,47 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
return hr;
}
+HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
+ IDirectMusicObject **dmobj)
+{
+ struct chunk_entry chunk = {.parent = list};
+ IDirectMusicGetLoader *getloader;
+ IDirectMusicLoader *loader;
+ DMUS_OBJECTDESC desc;
+ DMUS_IO_REFERENCE reference;
+ HRESULT hr;
+
+ if (FAILED(hr = stream_next_chunk(stream, &chunk)))
+ return hr;
+ if (chunk.id != DMUS_FOURCC_REF_CHUNK)
+ return DMUS_E_UNSUPPORTED_STREAM;
+
+ if (FAILED(hr = stream_chunk_get_data(stream, &chunk, &reference, sizeof(reference)))) {
+ WARN("Failed to read data of %s\n", debugstr_chunk(&chunk));
+ return hr;
+ }
+ TRACE("REFERENCE guidClassID %s, dwValidData %#x\n", debugstr_dmguid(&reference.guidClassID),
+ reference.dwValidData);
+
+ if (FAILED(hr = dmobj_parsedescriptor(stream, list, &desc, reference.dwValidData)))
+ return hr;
+ desc.guidClass = reference.guidClassID;
+ desc.dwValidData |= DMUS_OBJ_CLASS;
+ dump_DMUS_OBJECTDESC(&desc);
+
+ if (FAILED(hr = IStream_QueryInterface(stream, &IID_IDirectMusicGetLoader, (void**)&getloader)))
+ return hr;
+ hr = IDirectMusicGetLoader_GetLoader(getloader, &loader);
+ IDirectMusicGetLoader_Release(getloader);
+ if (FAILED(hr))
+ return hr;
+
+ hr = IDirectMusicLoader_GetObject(loader, &desc, &IID_IDirectMusicObject, (void**)dmobj);
+ IDirectMusicLoader_Release(loader);
+
+ return hr;
+}
+
/* Generic IPersistStream methods */
static inline struct dmobject *impl_from_IPersistStream(IPersistStream *iface)
{
diff --git a/dlls/dswave/dmobject.h b/dlls/dswave/dmobject.h
index d347020691c..afe721dc824 100644
--- a/dlls/dswave/dmobject.h
+++ b/dlls/dswave/dmobject.h
@@ -33,8 +33,10 @@ struct chunk_entry {
HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
-HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
+HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk) DECLSPEC_HIDDEN;
+HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
+ unsigned int *count, DWORD elem_size) DECLSPEC_HIDDEN;
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
ULONG size) DECLSPEC_HIDDEN;
HRESULT stream_chunk_get_wstr(IStream *stream, const struct chunk_entry *chunk, WCHAR *str,
@@ -89,6 +91,10 @@ HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff,
#define DMUS_OBJ_NAME_INAM 0x1000 /* 'INAM' chunk in UNFO list */
#define DMUS_OBJ_NAME_INFO 0x2000 /* 'INAM' chunk in INFO list */
+/* 'DMRF' (reference list) helper */
+HRESULT dmobj_parsereference(IStream *stream, const struct chunk_entry *list,
+ IDirectMusicObject **dmobj) DECLSPEC_HIDDEN;
+
/* Generic IPersistStream methods */
HRESULT WINAPI dmobj_IPersistStream_QueryInterface(IPersistStream *iface, REFIID riid,
void **ret_iface) DECLSPEC_HIDDEN;
--
2.26.2
1
0
[PATCH v3 2/2] winegstreamer: Set MF_MT_ALL_SAMPLES_INDEPENDENT attribute on raw video media types.
by Derek Lesho 30 Nov '20
by Derek Lesho 30 Nov '20
30 Nov '20
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
---
v3: Reword commit name.
---
dlls/winegstreamer/mfplat.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index 07dfae64f4f..50cd93b62d1 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -610,6 +610,7 @@ IMFMediaType *mf_media_type_from_caps(const GstCaps *caps)
unsigned int i;
IMFMediaType_SetUINT32(media_type, &MF_MT_COMPRESSED, FALSE);
+ IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
/* First try FOURCC */
if ((fourcc_subtype.Data1 = gst_video_format_to_fourcc(video_info.finfo->format)))
--
2.29.2
1
0
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
---
dlls/winegstreamer/media_source.c | 29 +++++++++++++++++++++++++++--
1 file changed, 27 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
index 5c502cf3ed5..7d677e39feb 100644
--- a/dlls/winegstreamer/media_source.c
+++ b/dlls/winegstreamer/media_source.c
@@ -64,6 +64,7 @@ struct media_stream
enum source_async_op
{
SOURCE_ASYNC_START,
+ SOURCE_ASYNC_STOP,
SOURCE_ASYNC_REQUEST_SAMPLE,
};
@@ -343,6 +344,22 @@ static void start_pipeline(struct media_source *source, struct source_async_comm
gst_element_set_state(source->container, GST_STATE_PLAYING);
}
+static void stop_pipeline(struct media_source *source)
+{
+ gst_element_set_state(source->container, GST_STATE_PAUSED);
+
+ for (unsigned int i = 0; i < source->stream_count; i++)
+ {
+ struct media_stream *stream = source->streams[i];
+ if (stream->state != STREAM_INACTIVE)
+ IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamStopped, &GUID_NULL, S_OK, NULL);
+ }
+
+ IMFMediaEventQueue_QueueEventParamVar(source->event_queue, MESourceStopped, &GUID_NULL, S_OK, NULL);
+
+ source->state = SOURCE_STOPPED;
+}
+
static void dispatch_end_of_presentation(struct media_source *source)
{
PROPVARIANT empty = {.vt = VT_EMPTY};
@@ -417,6 +434,9 @@ static HRESULT WINAPI source_async_commands_Invoke(IMFAsyncCallback *iface, IMFA
case SOURCE_ASYNC_START:
start_pipeline(source, command);
break;
+ case SOURCE_ASYNC_STOP:
+ stop_pipeline(source);
+ break;
case SOURCE_ASYNC_REQUEST_SAMPLE:
wait_on_sample(command->u.request_sample.stream, command->u.request_sample.token);
break;
@@ -1087,13 +1107,18 @@ static HRESULT WINAPI media_source_Start(IMFMediaSource *iface, IMFPresentationD
static HRESULT WINAPI media_source_Stop(IMFMediaSource *iface)
{
struct media_source *source = impl_from_IMFMediaSource(iface);
+ struct source_async_command *command;
+ HRESULT hr;
- FIXME("(%p): stub\n", source);
+ TRACE("(%p)\n", source);
if (source->state == SOURCE_SHUTDOWN)
return MF_E_SHUTDOWN;
- return E_NOTIMPL;
+ if (SUCCEEDED(hr = source_create_async_op(SOURCE_ASYNC_STOP, &command)))
+ hr = MFPutWorkItem(source->async_commands_queue, &source->async_commands_callback, &command->IUnknown_iface);
+
+ return hr;
}
static HRESULT WINAPI media_source_Pause(IMFMediaSource *iface)
--
2.29.2
2
5
[PATCH 5/5] wined3d: Use command buffer IDs for synchronisation in wined3d_buffer_gl_sync_apple().
by Henri Verbeet 30 Nov '20
by Henri Verbeet 30 Nov '20
30 Nov '20
Analogous to the Vulkan adapter. This is slightly awkward in OpenGL
because it doesn't have explicit command buffers like Vulkan, but
calling wined3d_context_gl_submit_command_fence() on swapchain present
works well enough in practice. The main advantage of this approach is that it
avoids using a separate fence for each usage of each bo.
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/wined3d/adapter_gl.c | 2 +
dlls/wined3d/buffer.c | 61 ++--------------
dlls/wined3d/context.c | 4 -
dlls/wined3d/context_gl.c | 130 +++++++++++++++++++++++++++------
dlls/wined3d/query.c | 2 +-
dlls/wined3d/swapchain.c | 1 +
dlls/wined3d/wined3d_private.h | 34 +++++++--
7 files changed, 146 insertions(+), 88 deletions(-)
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c
index cb382cd6734..4781622d530 100644
--- a/dlls/wined3d/adapter_gl.c
+++ b/dlls/wined3d/adapter_gl.c
@@ -4256,6 +4256,8 @@ static HRESULT adapter_gl_create_device(struct wined3d *wined3d, const struct wi
if (!(device_gl = heap_alloc_zero(sizeof(*device_gl))))
return E_OUTOFMEMORY;
+ device_gl->current_fence_id = 1;
+
if (FAILED(hr = wined3d_device_init(&device_gl->d, wined3d, adapter->ordinal, device_type, focus_window,
flags, surface_alignment, levels, level_count, adapter->gl_info.supported, device_parent)))
{
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index 61e35dc1e45..82051453ef1 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -187,11 +187,6 @@ static void wined3d_buffer_gl_destroy_buffer_object(struct wined3d_buffer_gl *bu
wined3d_context_gl_destroy_bo(context_gl, &buffer_gl->bo);
buffer_gl->b.buffer_object = 0;
- if (buffer_gl->b.fence)
- {
- wined3d_fence_destroy(buffer_gl->b.fence);
- buffer_gl->b.fence = NULL;
- }
buffer_gl->b.flags &= ~WINED3D_BUFFER_APPLESYNC;
}
@@ -746,9 +741,9 @@ void * CDECL wined3d_buffer_get_parent(const struct wined3d_buffer *buffer)
static void wined3d_buffer_gl_sync_apple(struct wined3d_buffer_gl *buffer_gl,
uint32_t flags, struct wined3d_context_gl *context_gl)
{
+ struct wined3d_device_gl *device_gl = wined3d_device_gl(buffer_gl->b.resource.device);
const struct wined3d_gl_info *gl_info = context_gl->gl_info;
- enum wined3d_fence_result ret;
- HRESULT hr;
+ struct wined3d_bo_gl *bo = &buffer_gl->bo;
/* No fencing needs to be done if the app promises not to overwrite
* existing data. */
@@ -759,59 +754,17 @@ static void wined3d_buffer_gl_sync_apple(struct wined3d_buffer_gl *buffer_gl,
{
wined3d_buffer_gl_bind(buffer_gl, context_gl);
- GL_EXTCALL(glBufferData(buffer_gl->bo.binding, buffer_gl->b.resource.size, NULL, buffer_gl->bo.usage));
+ GL_EXTCALL(glBufferData(bo->binding, buffer_gl->b.resource.size, NULL, bo->usage));
checkGLcall("glBufferData");
- return;
- }
-
- if (!buffer_gl->b.fence)
- {
- TRACE("Creating fence for buffer %p.\n", buffer_gl);
-
- if (FAILED(hr = wined3d_fence_create(buffer_gl->b.resource.device, &buffer_gl->b.fence)))
- {
- if (hr == WINED3DERR_NOTAVAILABLE)
- FIXME("Fences not supported, dropping async buffer locks.\n");
- else
- ERR("Failed to create fence, hr %#x.\n", hr);
- goto drop_fence;
- }
-
- /* Since we don't know about old draws a glFinish is needed once */
- gl_info->gl_ops.gl.p_glFinish();
+ bo->command_fence_id = 0;
return;
}
TRACE("Synchronizing buffer %p.\n", buffer_gl);
- ret = wined3d_fence_wait(buffer_gl->b.fence, buffer_gl->b.resource.device);
- switch (ret)
- {
- case WINED3D_FENCE_NOT_STARTED:
- case WINED3D_FENCE_OK:
- /* All done */
- return;
-
- case WINED3D_FENCE_WRONG_THREAD:
- WARN("Cannot synchronize buffer lock due to a thread conflict.\n");
- goto drop_fence;
-
- default:
- ERR("wined3d_fence_wait() returned %u, dropping async buffer locks.\n", ret);
- goto drop_fence;
- }
-drop_fence:
- if (buffer_gl->b.fence)
- {
- wined3d_fence_destroy(buffer_gl->b.fence);
- buffer_gl->b.fence = NULL;
- }
-
- gl_info->gl_ops.gl.p_glFinish();
- wined3d_buffer_gl_bind(buffer_gl, context_gl);
- GL_EXTCALL(glBufferParameteriAPPLE(buffer_gl->bo.binding, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE));
- checkGLcall("glBufferParameteriAPPLE(buffer_gl->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE)");
- buffer_gl->b.flags &= ~WINED3D_BUFFER_APPLESYNC;
+ if (bo->command_fence_id == device_gl->current_fence_id)
+ wined3d_context_gl_submit_command_fence(context_gl);
+ wined3d_context_gl_wait_command_fence(context_gl, bo->command_fence_id);
}
static void buffer_mark_used(struct wined3d_buffer *buffer)
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index ee2659ce23a..b52df0bd11e 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -271,7 +271,6 @@ void context_update_stream_info(struct wined3d_context *context, const struct wi
wined3d_stream_info_from_declaration(stream_info, state, d3d_info);
stream_info->all_vbo = 1;
- context->buffer_fence_count = 0;
for (i = 0, map = stream_info->use_map; map; map >>= 1, ++i)
{
struct wined3d_stream_info_element *element;
@@ -312,9 +311,6 @@ void context_update_stream_info(struct wined3d_context *context, const struct wi
if (!element->data.buffer_object)
stream_info->all_vbo = 0;
- if (buffer->fence)
- context->buffer_fences[context->buffer_fence_count++] = buffer->fence;
-
TRACE("Load array %u %s.\n", i, debug_bo_address(&element->data));
}
diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c
index 12e5e088713..ee1adfcf559 100644
--- a/dlls/wined3d/context_gl.c
+++ b/dlls/wined3d/context_gl.c
@@ -1374,6 +1374,10 @@ static void wined3d_context_gl_cleanup(struct wined3d_context_gl *context_gl)
if (context_gl->valid)
{
+ wined3d_context_gl_submit_command_fence(context_gl);
+ wined3d_context_gl_wait_command_fence(context_gl,
+ wined3d_device_gl(context_gl->c.device)->current_fence_id - 1);
+
if (context_gl->dummy_arbfp_prog)
GL_EXTCALL(glDeleteProgramsARB(1, &context_gl->dummy_arbfp_prog));
@@ -1422,6 +1426,7 @@ static void wined3d_context_gl_cleanup(struct wined3d_context_gl *context_gl)
checkGLcall("context cleanup");
}
+ heap_free(context_gl->submitted.fences);
heap_free(context_gl->free_pipeline_statistics_queries);
heap_free(context_gl->free_so_statistics_queries);
heap_free(context_gl->free_timestamp_queries);
@@ -2571,6 +2576,80 @@ void wined3d_context_gl_bind_texture(struct wined3d_context_gl *context_gl, GLen
checkGLcall("bind texture");
}
+static void wined3d_context_gl_poll_fences(struct wined3d_context_gl *context_gl)
+{
+ struct wined3d_device_gl *device_gl = wined3d_device_gl(context_gl->c.device);
+ struct wined3d_command_fence_gl *f;
+ SIZE_T i;
+
+ for (i = 0; i < context_gl->submitted.fence_count; ++i)
+ {
+ f = &context_gl->submitted.fences[i];
+
+ if (f->id > device_gl->completed_fence_id)
+ {
+ if (wined3d_fence_test(f->fence, &device_gl->d, 0) != WINED3D_FENCE_OK)
+ continue;
+ device_gl->completed_fence_id = f->id;
+ }
+
+ wined3d_fence_destroy(f->fence);
+ if (i != context_gl->submitted.fence_count - 1)
+ *f = context_gl->submitted.fences[context_gl->submitted.fence_count - 1];
+ --context_gl->submitted.fence_count;
+ }
+}
+
+void wined3d_context_gl_wait_command_fence(struct wined3d_context_gl *context_gl, uint64_t id)
+{
+ struct wined3d_device_gl *device_gl = wined3d_device_gl(context_gl->c.device);
+ enum wined3d_fence_result ret;
+ SIZE_T i;
+
+ if (id <= device_gl->completed_fence_id
+ || id > device_gl->current_fence_id) /* In case the fence ID wrapped. */
+ return;
+
+ for (i = 0; i < context_gl->submitted.fence_count; ++i)
+ {
+ if (context_gl->submitted.fences[i].id != id)
+ continue;
+
+ if ((ret = wined3d_fence_wait(context_gl->submitted.fences[i].fence, &device_gl->d)) != WINED3D_FENCE_OK)
+ ERR("Failed to wait for command fence with id 0x%s, ret %#x.\n", wine_dbgstr_longlong(id), ret);
+ wined3d_context_gl_poll_fences(context_gl);
+ return;
+ }
+
+ ERR("Failed to find fence for command fence with id 0x%s.\n", wine_dbgstr_longlong(id));
+}
+
+void wined3d_context_gl_submit_command_fence(struct wined3d_context_gl *context_gl)
+{
+ struct wined3d_device_gl *device_gl = wined3d_device_gl(context_gl->c.device);
+ struct wined3d_command_fence_gl *f;
+ HRESULT hr;
+
+ if (!wined3d_array_reserve((void **)&context_gl->submitted.fences, &context_gl->submitted.fences_size,
+ context_gl->submitted.fence_count + 1, sizeof(*context_gl->submitted.fences)))
+ ERR("Failed to grow submitted command buffer array.\n");
+
+ f = &context_gl->submitted.fences[context_gl->submitted.fence_count++];
+ f->id = device_gl->current_fence_id;
+ if (FAILED(hr = wined3d_fence_create(&device_gl->d, &f->fence)))
+ ERR("Failed to create fence, hr %#x.\n", hr);
+ wined3d_fence_issue(f->fence, &device_gl->d);
+
+ /* We don't expect this to ever happen, but handle it anyway. */
+ if (!++device_gl->current_fence_id)
+ {
+ wined3d_context_gl_wait_command_fence(context_gl, device_gl->current_fence_id - 1);
+ device_gl->completed_fence_id = 0;
+ device_gl->current_fence_id = 1;
+ }
+ wined3d_context_gl_poll_fences(context_gl);
+}
+
void *wined3d_context_gl_map_bo_address(struct wined3d_context_gl *context_gl,
const struct wined3d_bo_address *data, size_t size, uint32_t flags)
{
@@ -2728,6 +2807,8 @@ bool wined3d_context_gl_create_bo(struct wined3d_context_gl *context_gl, GLsizei
bo->id = id;
bo->binding = binding;
bo->usage = usage;
+ bo->command_fence_id = 0;
+
return true;
}
@@ -3605,7 +3686,7 @@ static BOOL context_apply_draw_state(struct wined3d_context *context,
const struct wined3d_gl_info *gl_info = context_gl->gl_info;
const struct wined3d_fb_state *fb = &state->fb;
unsigned int i, base;
- WORD map;
+ uint32_t map;
context->uses_fbo_attached_resources = 0;
@@ -3638,24 +3719,36 @@ static BOOL context_apply_draw_state(struct wined3d_context *context,
{
context_update_stream_info(context, state);
}
- else
+
+ map = context->stream_info.use_map;
+ while (map)
{
- for (i = 0, map = context->stream_info.use_map; map; map >>= 1, ++i)
- {
- if (map & 1)
- wined3d_buffer_load(state->streams[context->stream_info.elements[i].stream_idx].buffer,
- context, state);
- }
- /* Loading the buffers above may have invalidated the stream info. */
- if (isStateDirty(context, STATE_STREAMSRC))
- context_update_stream_info(context, state);
+ const struct wined3d_stream_info_element *e;
+ struct wined3d_buffer_gl *buffer_gl;
+
+ e = &context->stream_info.elements[wined3d_bit_scan(&map)];
+ buffer_gl = wined3d_buffer_gl(state->streams[e->stream_idx].buffer);
+
+ wined3d_buffer_load(&buffer_gl->b, context, state);
+ wined3d_context_gl_reference_bo(context_gl, &buffer_gl->bo);
}
+ /* Loading the buffers above may have invalidated the stream info. */
+ if (wined3d_context_is_graphics_state_dirty(context, STATE_STREAMSRC))
+ context_update_stream_info(context, state);
+
if (indexed && state->index_buffer)
{
+ struct wined3d_buffer_gl *buffer_gl = wined3d_buffer_gl(state->index_buffer);
+
if (context->stream_info.all_vbo)
- wined3d_buffer_load(state->index_buffer, context, state);
+ {
+ wined3d_buffer_load(&buffer_gl->b, context, state);
+ wined3d_context_gl_reference_bo(context_gl, &buffer_gl->bo);
+ }
else
- wined3d_buffer_load_sysmem(state->index_buffer, context);
+ {
+ wined3d_buffer_load_sysmem(&buffer_gl->b, context);
+ }
}
for (i = 0, base = 0; i < ARRAY_SIZE(context->dirty_graphics_states); ++i)
@@ -4475,7 +4568,6 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s
const struct wined3d_stream_info *stream_info;
struct wined3d_rendertarget_view *dsv, *rtv;
struct wined3d_stream_info si_emulated;
- struct wined3d_fence *ib_fence = NULL;
const struct wined3d_gl_info *gl_info;
struct wined3d_context_gl *context_gl;
struct wined3d_context *context;
@@ -4573,14 +4665,9 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s
{
struct wined3d_buffer *index_buffer = state->index_buffer;
if (!index_buffer->buffer_object || !stream_info->all_vbo)
- {
idx_data = index_buffer->resource.heap_memory;
- }
else
- {
- ib_fence = index_buffer->fence;
idx_data = NULL;
- }
idx_data = (const BYTE *)idx_data + state->index_offset;
if (state->index_format == WINED3DFMT_R16_UINT)
@@ -4719,11 +4806,6 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s
checkGLcall("disable rasterizer discard");
}
- if (ib_fence)
- wined3d_fence_issue(ib_fence, device);
- for (i = 0; i < context->buffer_fence_count; ++i)
- wined3d_fence_issue(context->buffer_fences[i], device);
-
context_release(context);
TRACE("Draw completed.\n");
diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c
index 5aca4a2c5a4..9e0e22b32e5 100644
--- a/dlls/wined3d/query.c
+++ b/dlls/wined3d/query.c
@@ -180,7 +180,7 @@ static BOOL wined3d_fence_supported(const struct wined3d_gl_info *gl_info)
return gl_info->supported[ARB_SYNC] || gl_info->supported[NV_FENCE] || gl_info->supported[APPLE_FENCE];
}
-static enum wined3d_fence_result wined3d_fence_test(const struct wined3d_fence *fence,
+enum wined3d_fence_result wined3d_fence_test(const struct wined3d_fence *fence,
struct wined3d_device *device, DWORD flags)
{
const struct wined3d_gl_info *gl_info;
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index 7e46e5c6150..ffffc18aa84 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -559,6 +559,7 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain,
/* call wglSwapBuffers through the gl table to avoid confusing the Steam overlay */
gl_info->gl_ops.wgl.p_wglSwapBuffers(context_gl->dc);
+ wined3d_context_gl_submit_command_fence(context_gl);
wined3d_swapchain_gl_rotate(swapchain, context);
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 3dcd3e26846..a7baff857d0 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1540,6 +1540,8 @@ struct wined3d_bo_gl
GLuint id;
GLenum binding;
GLenum usage;
+
+ uint64_t command_fence_id;
};
static inline GLuint wined3d_bo_gl_id(uintptr_t bo)
@@ -1842,6 +1844,8 @@ void wined3d_fence_destroy(struct wined3d_fence *fence) DECLSPEC_HIDDEN;
void wined3d_fence_issue(struct wined3d_fence *fence, struct wined3d_device *device) DECLSPEC_HIDDEN;
enum wined3d_fence_result wined3d_fence_wait(const struct wined3d_fence *fence,
struct wined3d_device *device) DECLSPEC_HIDDEN;
+enum wined3d_fence_result wined3d_fence_test(const struct wined3d_fence *fence,
+ struct wined3d_device *device, DWORD flags) DECLSPEC_HIDDEN;
/* Direct3D terminology with little modifications. We do not have an issued
* state because only the driver knows about it, but we have a created state
@@ -2105,10 +2109,6 @@ struct wined3d_context
struct wined3d_stream_info stream_info;
- /* Fences for GL_APPLE_flush_buffer_range */
- struct wined3d_fence *buffer_fences[MAX_ATTRIBS];
- unsigned int buffer_fence_count;
-
unsigned int viewport_count;
unsigned int scissor_rect_count;
};
@@ -2127,6 +2127,12 @@ void context_update_stream_info(struct wined3d_context *context, const struct wi
HRESULT wined3d_context_no3d_init(struct wined3d_context *context_no3d,
struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
+struct wined3d_command_fence_gl
+{
+ uint64_t id;
+ struct wined3d_fence *fence;
+};
+
struct wined3d_context_gl
{
struct wined3d_context c;
@@ -2214,6 +2220,13 @@ struct wined3d_context_gl
GLfloat colour[4], fog_start, fog_end, fog_colour[4];
GLuint dummy_arbfp_prog;
+
+ struct
+ {
+ struct wined3d_command_fence_gl *fences;
+ SIZE_T fences_size;
+ SIZE_T fence_count;
+ } submitted;
};
static inline struct wined3d_context_gl *wined3d_context_gl(struct wined3d_context *context)
@@ -2287,6 +2300,7 @@ struct wined3d_context_gl *wined3d_context_gl_reacquire(struct wined3d_context_g
void wined3d_context_gl_release(struct wined3d_context_gl *context_gl) DECLSPEC_HIDDEN;
BOOL wined3d_context_gl_set_current(struct wined3d_context_gl *context_gl) DECLSPEC_HIDDEN;
void wined3d_context_gl_set_draw_buffer(struct wined3d_context_gl *context_gl, GLenum buffer) DECLSPEC_HIDDEN;
+void wined3d_context_gl_submit_command_fence(struct wined3d_context_gl *context_gl) DECLSPEC_HIDDEN;
void wined3d_context_gl_texture_update(struct wined3d_context_gl *context_gl,
const struct wined3d_texture_gl *texture_gl) DECLSPEC_HIDDEN;
void wined3d_context_gl_unload_tex_coords(const struct wined3d_context_gl *context_gl) DECLSPEC_HIDDEN;
@@ -2294,6 +2308,7 @@ void wined3d_context_gl_unmap_bo_address(struct wined3d_context_gl *context_gl,
unsigned int range_count, const struct wined3d_range *ranges) DECLSPEC_HIDDEN;
void wined3d_context_gl_update_stream_sources(struct wined3d_context_gl *context_gl,
const struct wined3d_state *state) DECLSPEC_HIDDEN;
+void wined3d_context_gl_wait_command_fence(struct wined3d_context_gl *context_gl, uint64_t id) DECLSPEC_HIDDEN;
struct wined3d_command_buffer_vk
{
@@ -3803,6 +3818,9 @@ struct wined3d_device_gl
/* Textures for when no other textures are bound. */
struct wined3d_dummy_textures dummy_textures;
+
+ uint64_t completed_fence_id;
+ uint64_t current_fence_id;
};
static inline struct wined3d_device_gl *wined3d_device_gl(struct wined3d_device *device)
@@ -4789,7 +4807,6 @@ struct wined3d_buffer
struct wined3d_range *maps;
SIZE_T maps_size, modified_areas;
- struct wined3d_fence *fence;
/* conversion stuff */
UINT decl_change_count, full_conversion_count;
@@ -6298,6 +6315,13 @@ static inline bool wined3d_primitive_type_is_list(enum wined3d_primitive_type t)
|| t == WINED3D_PT_PATCH;
}
+static inline void wined3d_context_gl_reference_bo(struct wined3d_context_gl *context_gl, struct wined3d_bo_gl *bo_gl)
+{
+ struct wined3d_device_gl *device_gl = wined3d_device_gl(context_gl->c.device);
+
+ bo_gl->command_fence_id = device_gl->current_fence_id;
+}
+
/* The WNDCLASS-Name for the fake window which we use to retrieve the GL capabilities */
#define WINED3D_OPENGL_WINDOW_CLASS_NAME "WineD3D_OpenGL"
--
2.20.1
2
1
From: Matteo Bruni <mbruni(a)codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/wined3d/buffer.c | 4 +++-
dlls/wined3d/context_gl.c | 11 +++++++----
dlls/wined3d/resource.c | 15 +++++++++++++++
dlls/wined3d/texture.c | 4 ++--
dlls/wined3d/view.c | 4 ++--
dlls/wined3d/wined3d_private.h | 5 +++--
6 files changed, 32 insertions(+), 11 deletions(-)
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index 285ae7231ec..61e35dc1e45 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -201,6 +201,7 @@ static BOOL wined3d_buffer_gl_create_buffer_object(struct wined3d_buffer_gl *buf
{
const struct wined3d_gl_info *gl_info = context_gl->gl_info;
GLenum usage = GL_STATIC_DRAW;
+ GLbitfield gl_storage_flags;
struct wined3d_bo_gl *bo;
bool coherent = true;
GLsizeiptr size;
@@ -216,8 +217,9 @@ static BOOL wined3d_buffer_gl_create_buffer_object(struct wined3d_buffer_gl *buf
usage = GL_STREAM_DRAW_ARB;
coherent = false;
}
+ gl_storage_flags = wined3d_resource_gl_storage_flags(&buffer_gl->b.resource);
bo = &buffer_gl->bo;
- if (!wined3d_context_gl_create_bo(context_gl, size, binding, usage, coherent, bo))
+ if (!wined3d_context_gl_create_bo(context_gl, size, binding, usage, coherent, gl_storage_flags, bo))
{
ERR("Failed to create OpenGL buffer object.\n");
buffer_gl->b.flags &= ~WINED3D_BUFFER_USE_BO;
diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c
index 567d6ba56b7..12e5e088713 100644
--- a/dlls/wined3d/context_gl.c
+++ b/dlls/wined3d/context_gl.c
@@ -2694,13 +2694,13 @@ void wined3d_context_gl_destroy_bo(struct wined3d_context_gl *context_gl, struct
}
bool wined3d_context_gl_create_bo(struct wined3d_context_gl *context_gl, GLsizeiptr size,
- GLenum binding, GLenum usage, bool coherent, struct wined3d_bo_gl *bo)
+ GLenum binding, GLenum usage, bool coherent, GLbitfield flags, struct wined3d_bo_gl *bo)
{
const struct wined3d_gl_info *gl_info = context_gl->gl_info;
GLuint id = 0;
- TRACE("context_gl %p, size %lu, binding %#x, usage %#x, coherent %#x, bo %p.\n",
- context_gl, size, binding, usage, coherent, bo);
+ TRACE("context_gl %p, size %lu, binding %#x, usage %#x, coherent %#x, flags %#x, bo %p.\n",
+ context_gl, size, binding, usage, coherent, flags, bo);
GL_EXTCALL(glGenBuffers(1, &id));
if (!id)
@@ -2716,7 +2716,10 @@ bool wined3d_context_gl_create_bo(struct wined3d_context_gl *context_gl, GLsizei
GL_EXTCALL(glBufferParameteriAPPLE(binding, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE));
}
- GL_EXTCALL(glBufferData(binding, size, NULL, usage));
+ if (gl_info->supported[ARB_BUFFER_STORAGE])
+ GL_EXTCALL(glBufferStorage(binding, size, NULL, flags | GL_DYNAMIC_STORAGE_BIT));
+ else
+ GL_EXTCALL(glBufferData(binding, size, NULL, usage));
wined3d_context_gl_bind_bo(context_gl, binding, 0);
checkGLcall("buffer object creation");
diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c
index c8d5fecf9d9..97b8b68374d 100644
--- a/dlls/wined3d/resource.c
+++ b/dlls/wined3d/resource.c
@@ -428,6 +428,21 @@ void wined3d_resource_free_sysmem(struct wined3d_resource *resource)
resource->heap_memory = NULL;
}
+GLbitfield wined3d_resource_gl_storage_flags(const struct wined3d_resource *resource)
+{
+ uint32_t access = resource->access;
+ GLbitfield flags = 0;
+
+ if (resource->usage & WINED3DUSAGE_DYNAMIC)
+ flags |= GL_CLIENT_STORAGE_BIT;
+ if (access & WINED3D_RESOURCE_ACCESS_MAP_W)
+ flags |= GL_MAP_WRITE_BIT;
+ if (access & WINED3D_RESOURCE_ACCESS_MAP_R)
+ flags |= GL_MAP_READ_BIT;
+
+ return flags;
+}
+
GLbitfield wined3d_resource_gl_map_flags(DWORD d3d_flags)
{
GLbitfield ret = 0;
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index b311df0f896..b84b68c592b 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -1924,8 +1924,8 @@ static void wined3d_texture_gl_prepare_buffer_object(struct wined3d_texture_gl *
if (bo->id)
return;
- if (!wined3d_context_gl_create_bo(context_gl, sub_resource->size,
- GL_PIXEL_UNPACK_BUFFER, GL_STREAM_DRAW, true, bo))
+ if (!wined3d_context_gl_create_bo(context_gl, sub_resource->size, GL_PIXEL_UNPACK_BUFFER,
+ GL_STREAM_DRAW, true, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_CLIENT_STORAGE_BIT, bo))
return;
TRACE("Created buffer object %u for texture %p, sub-resource %u.\n", bo->id, texture_gl, sub_resource_idx);
diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c
index 1d77b0e44fb..4c85e2fefe4 100644
--- a/dlls/wined3d/view.c
+++ b/dlls/wined3d/view.c
@@ -1415,8 +1415,8 @@ static void wined3d_unordered_access_view_gl_cs_init(void *object)
struct wined3d_bo_gl *bo = &view_gl->counter_bo;
view_gl->v.counter_bo = (uintptr_t)bo;
- wined3d_context_gl_create_bo(context_gl, sizeof(uint32_t),
- GL_ATOMIC_COUNTER_BUFFER, GL_STATIC_DRAW, true, bo);
+ wined3d_context_gl_create_bo(context_gl, sizeof(uint32_t), GL_ATOMIC_COUNTER_BUFFER,
+ GL_STATIC_DRAW, true, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_CLIENT_STORAGE_BIT, bo);
wined3d_unordered_access_view_set_counter(&view_gl->v, 0);
}
context_release(&context_gl->c);
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 9b12295ec52..3dcd3e26846 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2256,8 +2256,8 @@ void wined3d_context_gl_bind_texture(struct wined3d_context_gl *context_gl,
void wined3d_context_gl_check_fbo_status(const struct wined3d_context_gl *context_gl, GLenum target) DECLSPEC_HIDDEN;
void wined3d_context_gl_copy_bo_address(struct wined3d_context_gl *context_gl,
const struct wined3d_bo_address *dst, const struct wined3d_bo_address *src, size_t size) DECLSPEC_HIDDEN;
-bool wined3d_context_gl_create_bo(struct wined3d_context_gl *context_gl, GLsizeiptr size,
- GLenum binding, GLenum usage, bool coherent, struct wined3d_bo_gl *bo) DECLSPEC_HIDDEN;
+bool wined3d_context_gl_create_bo(struct wined3d_context_gl *context_gl, GLsizeiptr size, GLenum binding,
+ GLenum usage, bool coherent, GLbitfield flags, struct wined3d_bo_gl *bo) DECLSPEC_HIDDEN;
void wined3d_context_gl_destroy(struct wined3d_context_gl *context_gl) DECLSPEC_HIDDEN;
void wined3d_context_gl_destroy_bo(struct wined3d_context_gl *context_gl, struct wined3d_bo_gl *bo) DECLSPEC_HIDDEN;
void wined3d_context_gl_draw_shaded_quad(struct wined3d_context_gl *context_gl, struct wined3d_texture_gl *texture_gl,
@@ -4049,6 +4049,7 @@ const struct wined3d_format *wined3d_resource_get_decompress_format(
unsigned int wined3d_resource_get_sample_count(const struct wined3d_resource *resource) DECLSPEC_HIDDEN;
GLbitfield wined3d_resource_gl_map_flags(DWORD d3d_flags) DECLSPEC_HIDDEN;
GLenum wined3d_resource_gl_legacy_map_flags(DWORD d3d_flags) DECLSPEC_HIDDEN;
+GLbitfield wined3d_resource_gl_storage_flags(const struct wined3d_resource *resource) DECLSPEC_HIDDEN;
BOOL wined3d_resource_is_offscreen(struct wined3d_resource *resource) DECLSPEC_HIDDEN;
BOOL wined3d_resource_prepare_sysmem(struct wined3d_resource *resource) DECLSPEC_HIDDEN;
void wined3d_resource_update_draw_binding(struct wined3d_resource *resource) DECLSPEC_HIDDEN;
--
2.20.1
2
1
30 Nov '20
From: Matteo Bruni <mbruni(a)codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/wined3d/buffer.c | 77 ++++++++--------------------------
dlls/wined3d/context_gl.c | 35 ++++++++++++++++
dlls/wined3d/texture.c | 20 ++++-----
dlls/wined3d/view.c | 22 ++++------
dlls/wined3d/wined3d_private.h | 2 +
5 files changed, 72 insertions(+), 84 deletions(-)
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index 0caf933724a..285ae7231ec 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -200,79 +200,38 @@ static BOOL wined3d_buffer_gl_create_buffer_object(struct wined3d_buffer_gl *buf
struct wined3d_context_gl *context_gl)
{
const struct wined3d_gl_info *gl_info = context_gl->gl_info;
+ GLenum usage = GL_STATIC_DRAW;
struct wined3d_bo_gl *bo;
- GLenum error;
+ bool coherent = true;
+ GLsizeiptr size;
+ GLenum binding;
TRACE("Creating an OpenGL buffer object for wined3d buffer %p with usage %s.\n",
buffer_gl, debug_d3dusage(buffer_gl->b.resource.usage));
- /* Make sure that the gl error is cleared. Do not use checkGLcall
- * here because checkGLcall just prints a fixme and continues. However,
- * if an error during VBO creation occurs we can fall back to non-VBO operation
- * with full functionality(but performance loss).
- */
- while (gl_info->gl_ops.gl.p_glGetError() != GL_NO_ERROR);
-
- /* Basically the FVF parameter passed to CreateVertexBuffer is no good.
- * The vertex declaration from the device determines how the data in the
- * buffer is interpreted. This means that on each draw call the buffer has
- * to be verified to check if the rhw and color values are in the correct
- * format. */
-
- bo = &buffer_gl->bo;
- GL_EXTCALL(glGenBuffers(1, &bo->id));
- bo->binding = wined3d_buffer_gl_binding_from_bind_flags(gl_info, buffer_gl->b.resource.bind_flags);
- bo->usage = GL_STATIC_DRAW;
- buffer_gl->b.buffer_object = (uintptr_t)bo;
- error = gl_info->gl_ops.gl.p_glGetError();
- if (!bo->id || error != GL_NO_ERROR)
- {
- ERR("Failed to create a BO with error %s (%#x).\n", debug_glerror(error), error);
- goto fail;
- }
-
- wined3d_buffer_gl_bind(buffer_gl, context_gl);
- error = gl_info->gl_ops.gl.p_glGetError();
- if (error != GL_NO_ERROR)
- {
- ERR("Failed to bind the BO with error %s (%#x).\n", debug_glerror(error), error);
- goto fail;
- }
-
+ size = buffer_gl->b.resource.size;
+ binding = wined3d_buffer_gl_binding_from_bind_flags(gl_info, buffer_gl->b.resource.bind_flags);
if (buffer_gl->b.resource.usage & WINED3DUSAGE_DYNAMIC)
{
- TRACE("Buffer has WINED3DUSAGE_DYNAMIC set.\n");
- bo->usage = GL_STREAM_DRAW_ARB;
-
- if (gl_info->supported[APPLE_FLUSH_BUFFER_RANGE])
- {
- GL_EXTCALL(glBufferParameteriAPPLE(bo->binding, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE));
- GL_EXTCALL(glBufferParameteriAPPLE(bo->binding, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE));
- checkGLcall("glBufferParameteriAPPLE");
- buffer_gl->b.flags |= WINED3D_BUFFER_APPLESYNC;
- }
- /* No setup is needed here for GL_ARB_map_buffer_range. */
+ usage = GL_STREAM_DRAW_ARB;
+ coherent = false;
}
-
- GL_EXTCALL(glBufferData(bo->binding, buffer_gl->b.resource.size, NULL, bo->usage));
- error = gl_info->gl_ops.gl.p_glGetError();
- if (error != GL_NO_ERROR)
+ bo = &buffer_gl->bo;
+ if (!wined3d_context_gl_create_bo(context_gl, size, binding, usage, coherent, bo))
{
- ERR("glBufferData failed with error %s (%#x).\n", debug_glerror(error), error);
- goto fail;
+ ERR("Failed to create OpenGL buffer object.\n");
+ buffer_gl->b.flags &= ~WINED3D_BUFFER_USE_BO;
+ buffer_clear_dirty_areas(&buffer_gl->b);
+ return FALSE;
}
+ if (!coherent && gl_info->supported[APPLE_FLUSH_BUFFER_RANGE])
+ buffer_gl->b.flags |= WINED3D_BUFFER_APPLESYNC;
+
+ buffer_gl->b.buffer_object = (uintptr_t)bo;
buffer_invalidate_bo_range(&buffer_gl->b, 0, 0);
return TRUE;
-
-fail:
- /* Clean up all BO init, but continue because we can work without a BO :-) */
- ERR("Failed to create a buffer object. Continuing, but performance issues may occur.\n");
- buffer_gl->b.flags &= ~WINED3D_BUFFER_USE_BO;
- wined3d_buffer_gl_destroy_buffer_object(buffer_gl, context_gl);
- buffer_clear_dirty_areas(&buffer_gl->b);
- return FALSE;
}
static BOOL buffer_process_converted_attribute(struct wined3d_buffer *buffer,
diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c
index 3a5718e6308..567d6ba56b7 100644
--- a/dlls/wined3d/context_gl.c
+++ b/dlls/wined3d/context_gl.c
@@ -2693,6 +2693,41 @@ void wined3d_context_gl_destroy_bo(struct wined3d_context_gl *context_gl, struct
bo->id = 0;
}
+bool wined3d_context_gl_create_bo(struct wined3d_context_gl *context_gl, GLsizeiptr size,
+ GLenum binding, GLenum usage, bool coherent, struct wined3d_bo_gl *bo)
+{
+ const struct wined3d_gl_info *gl_info = context_gl->gl_info;
+ GLuint id = 0;
+
+ TRACE("context_gl %p, size %lu, binding %#x, usage %#x, coherent %#x, bo %p.\n",
+ context_gl, size, binding, usage, coherent, bo);
+
+ GL_EXTCALL(glGenBuffers(1, &id));
+ if (!id)
+ {
+ checkGLcall("buffer object creation");
+ return false;
+ }
+ wined3d_context_gl_bind_bo(context_gl, binding, id);
+
+ if (!coherent && gl_info->supported[APPLE_FLUSH_BUFFER_RANGE])
+ {
+ GL_EXTCALL(glBufferParameteriAPPLE(binding, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE));
+ GL_EXTCALL(glBufferParameteriAPPLE(binding, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE));
+ }
+
+ GL_EXTCALL(glBufferData(binding, size, NULL, usage));
+
+ wined3d_context_gl_bind_bo(context_gl, binding, 0);
+ checkGLcall("buffer object creation");
+
+ TRACE("Created buffer object %u.\n", id);
+ bo->id = id;
+ bo->binding = binding;
+ bo->usage = usage;
+ return true;
+}
+
static void wined3d_context_gl_set_render_offscreen(struct wined3d_context_gl *context_gl, BOOL offscreen)
{
if (context_gl->c.render_offscreen == offscreen)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index 73821cc27a9..b311df0f896 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -1913,26 +1913,22 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, unsig
}
/* Context activation is done by the caller. */
-static void wined3d_texture_prepare_buffer_object(struct wined3d_texture *texture,
- unsigned int sub_resource_idx, const struct wined3d_gl_info *gl_info)
+static void wined3d_texture_gl_prepare_buffer_object(struct wined3d_texture_gl *texture_gl,
+ unsigned int sub_resource_idx, struct wined3d_context_gl *context_gl)
{
struct wined3d_texture_sub_resource *sub_resource;
struct wined3d_bo_gl *bo;
- sub_resource = &texture->sub_resources[sub_resource_idx];
+ sub_resource = &texture_gl->t.sub_resources[sub_resource_idx];
bo = &sub_resource->bo;
if (bo->id)
return;
- GL_EXTCALL(glGenBuffers(1, &bo->id));
- bo->binding = GL_PIXEL_UNPACK_BUFFER;
- bo->usage = GL_STREAM_DRAW;
- GL_EXTCALL(glBindBuffer(bo->binding, bo->id));
- GL_EXTCALL(glBufferData(bo->binding, sub_resource->size, NULL, bo->usage));
- GL_EXTCALL(glBindBuffer(bo->binding, 0));
- checkGLcall("Create buffer object");
+ if (!wined3d_context_gl_create_bo(context_gl, sub_resource->size,
+ GL_PIXEL_UNPACK_BUFFER, GL_STREAM_DRAW, true, bo))
+ return;
- TRACE("Created buffer object %u for texture %p, sub-resource %u.\n", bo->id, texture, sub_resource_idx);
+ TRACE("Created buffer object %u for texture %p, sub-resource %u.\n", bo->id, texture_gl, sub_resource_idx);
}
static void wined3d_texture_force_reload(struct wined3d_texture *texture)
@@ -3135,7 +3131,7 @@ static BOOL wined3d_texture_gl_prepare_location(struct wined3d_texture *texture,
: wined3d_resource_prepare_sysmem(&texture->resource);
case WINED3D_LOCATION_BUFFER:
- wined3d_texture_prepare_buffer_object(texture, sub_resource_idx, context_gl->gl_info);
+ wined3d_texture_gl_prepare_buffer_object(texture_gl, sub_resource_idx, context_gl);
return TRUE;
case WINED3D_LOCATION_TEXTURE_RGB:
diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c
index bf4c9ca5af1..1d77b0e44fb 100644
--- a/dlls/wined3d/view.c
+++ b/dlls/wined3d/view.c
@@ -1405,25 +1405,21 @@ static void wined3d_unordered_access_view_gl_cs_init(void *object)
if (resource->type == WINED3D_RTYPE_BUFFER)
{
struct wined3d_buffer *buffer = buffer_from_resource(resource);
- struct wined3d_context *context;
+ struct wined3d_context_gl *context_gl;
- context = context_acquire(resource->device, NULL, 0);
- gl_info = wined3d_context_gl(context)->gl_info;
- create_buffer_view(&view_gl->gl_view, context, desc, buffer, view_gl->v.format);
+ context_gl = wined3d_context_gl(context_acquire(resource->device, NULL, 0));
+ gl_info = context_gl->gl_info;
+ create_buffer_view(&view_gl->gl_view, &context_gl->c, desc, buffer, view_gl->v.format);
if (desc->flags & (WINED3D_VIEW_BUFFER_COUNTER | WINED3D_VIEW_BUFFER_APPEND))
{
struct wined3d_bo_gl *bo = &view_gl->counter_bo;
- static const GLuint initial_value = 0;
-
- GL_EXTCALL(glGenBuffers(1, &bo->id));
- bo->binding = GL_ATOMIC_COUNTER_BUFFER;
- bo->usage = GL_STATIC_DRAW;
- GL_EXTCALL(glBindBuffer(bo->binding, bo->id));
- GL_EXTCALL(glBufferData(bo->binding, sizeof(initial_value), &initial_value, bo->usage));
- checkGLcall("create atomic counter buffer");
+
view_gl->v.counter_bo = (uintptr_t)bo;
+ wined3d_context_gl_create_bo(context_gl, sizeof(uint32_t),
+ GL_ATOMIC_COUNTER_BUFFER, GL_STATIC_DRAW, true, bo);
+ wined3d_unordered_access_view_set_counter(&view_gl->v, 0);
}
- context_release(context);
+ context_release(&context_gl->c);
}
else
{
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index dbdb10a182a..9b12295ec52 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2256,6 +2256,8 @@ void wined3d_context_gl_bind_texture(struct wined3d_context_gl *context_gl,
void wined3d_context_gl_check_fbo_status(const struct wined3d_context_gl *context_gl, GLenum target) DECLSPEC_HIDDEN;
void wined3d_context_gl_copy_bo_address(struct wined3d_context_gl *context_gl,
const struct wined3d_bo_address *dst, const struct wined3d_bo_address *src, size_t size) DECLSPEC_HIDDEN;
+bool wined3d_context_gl_create_bo(struct wined3d_context_gl *context_gl, GLsizeiptr size,
+ GLenum binding, GLenum usage, bool coherent, struct wined3d_bo_gl *bo) DECLSPEC_HIDDEN;
void wined3d_context_gl_destroy(struct wined3d_context_gl *context_gl) DECLSPEC_HIDDEN;
void wined3d_context_gl_destroy_bo(struct wined3d_context_gl *context_gl, struct wined3d_bo_gl *bo) DECLSPEC_HIDDEN;
void wined3d_context_gl_draw_shaded_quad(struct wined3d_context_gl *context_gl, struct wined3d_texture_gl *texture_gl,
--
2.20.1
2
1
30 Nov '20
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/wined3d/buffer.c | 10 ++++------
dlls/wined3d/texture.c | 3 ++-
dlls/wined3d/view.c | 3 ++-
dlls/wined3d/wined3d_private.h | 2 +-
4 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index 2b24e071c05..0caf933724a 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -200,7 +200,6 @@ static BOOL wined3d_buffer_gl_create_buffer_object(struct wined3d_buffer_gl *buf
struct wined3d_context_gl *context_gl)
{
const struct wined3d_gl_info *gl_info = context_gl->gl_info;
- GLenum gl_usage = GL_STATIC_DRAW;
struct wined3d_bo_gl *bo;
GLenum error;
@@ -223,6 +222,7 @@ static BOOL wined3d_buffer_gl_create_buffer_object(struct wined3d_buffer_gl *buf
bo = &buffer_gl->bo;
GL_EXTCALL(glGenBuffers(1, &bo->id));
bo->binding = wined3d_buffer_gl_binding_from_bind_flags(gl_info, buffer_gl->b.resource.bind_flags);
+ bo->usage = GL_STATIC_DRAW;
buffer_gl->b.buffer_object = (uintptr_t)bo;
error = gl_info->gl_ops.gl.p_glGetError();
if (!bo->id || error != GL_NO_ERROR)
@@ -242,7 +242,7 @@ static BOOL wined3d_buffer_gl_create_buffer_object(struct wined3d_buffer_gl *buf
if (buffer_gl->b.resource.usage & WINED3DUSAGE_DYNAMIC)
{
TRACE("Buffer has WINED3DUSAGE_DYNAMIC set.\n");
- gl_usage = GL_STREAM_DRAW_ARB;
+ bo->usage = GL_STREAM_DRAW_ARB;
if (gl_info->supported[APPLE_FLUSH_BUFFER_RANGE])
{
@@ -254,7 +254,7 @@ static BOOL wined3d_buffer_gl_create_buffer_object(struct wined3d_buffer_gl *buf
/* No setup is needed here for GL_ARB_map_buffer_range. */
}
- GL_EXTCALL(glBufferData(bo->binding, buffer_gl->b.resource.size, NULL, gl_usage));
+ GL_EXTCALL(glBufferData(bo->binding, buffer_gl->b.resource.size, NULL, bo->usage));
error = gl_info->gl_ops.gl.p_glGetError();
if (error != GL_NO_ERROR)
{
@@ -262,7 +262,6 @@ static BOOL wined3d_buffer_gl_create_buffer_object(struct wined3d_buffer_gl *buf
goto fail;
}
- buffer_gl->buffer_object_usage = gl_usage;
buffer_invalidate_bo_range(&buffer_gl->b, 0, 0);
return TRUE;
@@ -799,8 +798,7 @@ static void wined3d_buffer_gl_sync_apple(struct wined3d_buffer_gl *buffer_gl,
{
wined3d_buffer_gl_bind(buffer_gl, context_gl);
- GL_EXTCALL(glBufferData(buffer_gl->bo.binding, buffer_gl->b.resource.size,
- NULL, buffer_gl->buffer_object_usage));
+ GL_EXTCALL(glBufferData(buffer_gl->bo.binding, buffer_gl->b.resource.size, NULL, buffer_gl->bo.usage));
checkGLcall("glBufferData");
return;
}
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index 0aef891547a..73821cc27a9 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -1926,8 +1926,9 @@ static void wined3d_texture_prepare_buffer_object(struct wined3d_texture *textur
GL_EXTCALL(glGenBuffers(1, &bo->id));
bo->binding = GL_PIXEL_UNPACK_BUFFER;
+ bo->usage = GL_STREAM_DRAW;
GL_EXTCALL(glBindBuffer(bo->binding, bo->id));
- GL_EXTCALL(glBufferData(bo->binding, sub_resource->size, NULL, GL_STREAM_DRAW));
+ GL_EXTCALL(glBufferData(bo->binding, sub_resource->size, NULL, bo->usage));
GL_EXTCALL(glBindBuffer(bo->binding, 0));
checkGLcall("Create buffer object");
diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c
index a690bd4ae6b..bf4c9ca5af1 100644
--- a/dlls/wined3d/view.c
+++ b/dlls/wined3d/view.c
@@ -1417,8 +1417,9 @@ static void wined3d_unordered_access_view_gl_cs_init(void *object)
GL_EXTCALL(glGenBuffers(1, &bo->id));
bo->binding = GL_ATOMIC_COUNTER_BUFFER;
+ bo->usage = GL_STATIC_DRAW;
GL_EXTCALL(glBindBuffer(bo->binding, bo->id));
- GL_EXTCALL(glBufferData(bo->binding, sizeof(initial_value), &initial_value, GL_STATIC_DRAW));
+ GL_EXTCALL(glBufferData(bo->binding, sizeof(initial_value), &initial_value, bo->usage));
checkGLcall("create atomic counter buffer");
view_gl->v.counter_bo = (uintptr_t)bo;
}
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index fa718501e45..dbdb10a182a 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1539,6 +1539,7 @@ struct wined3d_bo_gl
{
GLuint id;
GLenum binding;
+ GLenum usage;
};
static inline GLuint wined3d_bo_gl_id(uintptr_t bo)
@@ -4825,7 +4826,6 @@ struct wined3d_buffer_gl
struct wined3d_buffer b;
struct wined3d_bo_gl bo;
- GLenum buffer_object_usage;
};
static inline struct wined3d_buffer_gl *wined3d_buffer_gl(struct wined3d_buffer *buffer)
--
2.20.1
2
1