ReactOS.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
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
List overview
Download
Ros-diffs
May 2018
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
May 2005
April 2005
March 2005
February 2005
January 2005
----- 2004 -----
December 2004
November 2004
October 2004
September 2004
August 2004
July 2004
June 2004
May 2004
April 2004
March 2004
February 2004
ros-diffs@reactos.org
23 participants
218 discussions
Start a n
N
ew thread
01/01: [DEVENUM_WINETEST] Sync with Wine Staging 3.9. CORE-14656
by Amine Khaldi
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6e5b60fcf4331299f2ac1…
commit 6e5b60fcf4331299f2ac1a1d5db0b61e689f2533 Author: Amine Khaldi <amine.khaldi(a)reactos.org> AuthorDate: Sun May 27 03:56:54 2018 +0100 Commit: Amine Khaldi <amine.khaldi(a)reactos.org> CommitDate: Sun May 27 03:56:54 2018 +0100 [DEVENUM_WINETEST] Sync with Wine Staging 3.9. CORE-14656 --- modules/rostests/winetests/devenum/CMakeLists.txt | 2 +- modules/rostests/winetests/devenum/devenum.c | 854 ++++++++++++++++++++-- 2 files changed, 797 insertions(+), 59 deletions(-) diff --git a/modules/rostests/winetests/devenum/CMakeLists.txt b/modules/rostests/winetests/devenum/CMakeLists.txt index acdbbb123d..840011078f 100644 --- a/modules/rostests/winetests/devenum/CMakeLists.txt +++ b/modules/rostests/winetests/devenum/CMakeLists.txt @@ -1,5 +1,5 @@ add_executable(devenum_winetest devenum.c testlist.c) set_module_type(devenum_winetest win32cui) -add_importlibs(devenum_winetest oleaut32 ole32 msvcrt kernel32) +add_importlibs(devenum_winetest advapi32 dsound msvfw32 oleaut32 ole32 winmm msvcrt kernel32) add_rostests_file(TARGET devenum_winetest) diff --git a/modules/rostests/winetests/devenum/devenum.c b/modules/rostests/winetests/devenum/devenum.c index 5a41183655..f47ab42026 100644 --- a/modules/rostests/winetests/devenum/devenum.c +++ b/modules/rostests/winetests/devenum/devenum.c @@ -27,60 +27,84 @@ #include "ole2.h" #include "strmif.h" #include "uuids.h" +#include "vfwmsgs.h" +#include "mmsystem.h" +#include "dsound.h" +#include "mmddk.h" +#include "vfw.h" + +DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); static const WCHAR friendly_name[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0}; static const WCHAR fcc_handlerW[] = {'F','c','c','H','a','n','d','l','e','r',0}; +static const WCHAR deviceW[] = {'@','d','e','v','i','c','e',':',0}; +static const WCHAR clsidW[] = {'C','L','S','I','D',0}; +static const WCHAR waveW[] = {'w','a','v','e',':',0}; static const WCHAR mrleW[] = {'m','r','l','e',0}; +static const WCHAR swW[] = {'s','w',':',0}; +static const WCHAR cmW[] = {'c','m',':',0}; +static const WCHAR backslashW[] = {'\\',0}; -struct category +static inline WCHAR *strchrW( const WCHAR *str, WCHAR ch ) { - const char * name; - const GUID * clsid; -}; + do { if (*str == ch) return (WCHAR *)str; } while (*str++); + return NULL; +} -static struct category am_categories[] = +static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n ) { - { "Legacy AM Filter category", &CLSID_LegacyAmFilterCategory }, - { "Audio renderer category", &CLSID_AudioRendererCategory }, - { "Midi renderer category", &CLSID_MidiRendererCategory }, - { "Audio input device category", &CLSID_AudioInputDeviceCategory }, - { "Video input device category", &CLSID_VideoInputDeviceCategory }, - { "Audio compressor category", &CLSID_AudioCompressorCategory }, - { "Video compressor category", &CLSID_VideoCompressorCategory } -}; + if (n <= 0) return 0; + while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; } + return *str1 - *str2; +} static void test_devenum(IBindCtx *bind_ctx) { - HRESULT res; + IEnumMoniker *enum_cat, *enum_moniker; ICreateDevEnum* create_devenum; - IEnumMoniker* enum_moniker = NULL; + IPropertyBag *prop_bag; + IMoniker *moniker; BOOL have_mrle = FALSE; - int i; + GUID cat_guid, clsid; + VARIANT var; + HRESULT hr; - res = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, + hr = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, &IID_ICreateDevEnum, (LPVOID*)&create_devenum); - if (res != S_OK) { - skip("Cannot create SystemDeviceEnum object (%x)\n", res); - return; - } + ok(hr == S_OK, "Failed to create devenum: %#x\n", hr); - for (i = 0; i < (sizeof(am_categories) / sizeof(struct category)); i++) + hr = ICreateDevEnum_CreateClassEnumerator(create_devenum, &CLSID_ActiveMovieCategories, &enum_cat, 0); + ok(hr == S_OK, "Failed to enum categories: %#x\n", hr); + + while (IEnumMoniker_Next(enum_cat, 1, &moniker, NULL) == S_OK) { + hr = IMoniker_BindToStorage(moniker, bind_ctx, NULL, &IID_IPropertyBag, (void **)&prop_bag); + ok(hr == S_OK, "IMoniker_BindToStorage failed: %#x\n", hr); + + VariantInit(&var); + hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL); + ok(hr == S_OK, "Failed to read FriendlyName: %#x\n", hr); + if (winetest_debug > 1) - trace("%s:\n", am_categories[i].name); + trace("%s:\n", wine_dbgstr_w(V_BSTR(&var))); + + VariantClear(&var); + hr = IPropertyBag_Read(prop_bag, clsidW, &var, NULL); + ok(hr == S_OK, "Failed to read CLSID: %#x\n", hr); - res = ICreateDevEnum_CreateClassEnumerator(create_devenum, am_categories[i].clsid, &enum_moniker, 0); - ok(SUCCEEDED(res), "Cannot create enum moniker (res = %x)\n", res); - if (res == S_OK) + hr = CLSIDFromString(V_BSTR(&var), &cat_guid); + ok(hr == S_OK, "got %#x\n", hr); + + IPropertyBag_Release(prop_bag); + IMoniker_Release(moniker); + + hr = ICreateDevEnum_CreateClassEnumerator(create_devenum, &cat_guid, &enum_moniker, 0); + ok(SUCCEEDED(hr), "Failed to enum devices: %#x\n", hr); + + if (hr == S_OK) { - IMoniker* moniker; while (IEnumMoniker_Next(enum_moniker, 1, &moniker, NULL) == S_OK) { - IPropertyBag* prop_bag = NULL; - VARIANT var; - HRESULT hr; - CLSID clsid = {0}; - hr = IMoniker_GetClassID(moniker, NULL); ok(hr == E_INVALIDARG, "IMoniker_GetClassID should failed %x\n", hr); @@ -93,36 +117,27 @@ static void test_devenum(IBindCtx *bind_ctx) hr = IMoniker_BindToStorage(moniker, bind_ctx, NULL, &IID_IPropertyBag, (LPVOID*)&prop_bag); ok(hr == S_OK, "IMoniker_BindToStorage failed with error %x\n", hr); - if (SUCCEEDED(hr)) - { - hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL); - ok((hr == S_OK) || broken(hr == 0x80070002), "IPropertyBag_Read failed with error %x\n", hr); + hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL); + ok(hr == S_OK, "IPropertyBag_Read failed: %#x\n", hr); - if (SUCCEEDED(hr)) - { - if (winetest_debug > 1) - trace(" %s\n", wine_dbgstr_w(V_BSTR(&var))); - VariantClear(&var); - } - else - { - trace(" ???\n"); - } + if (winetest_debug > 1) + trace(" %s\n", wine_dbgstr_w(V_BSTR(&var))); - if (IsEqualGUID(&CLSID_VideoCompressorCategory, am_categories[i].clsid)) { - /* Test well known compressor to ensure that we really enumerate codecs */ - hr = IPropertyBag_Read(prop_bag, fcc_handlerW, &var, NULL); - if (SUCCEEDED(hr)) { - ok(V_VT(&var) == VT_BSTR, "V_VT(var) = %d\n", V_VT(&var)); - if(!lstrcmpW(V_BSTR(&var), mrleW)) - have_mrle = TRUE; - VariantClear(&var); - } + if (IsEqualGUID(&CLSID_VideoCompressorCategory, &cat_guid)) { + /* Test well known compressor to ensure that we really enumerate codecs */ + hr = IPropertyBag_Read(prop_bag, fcc_handlerW, &var, NULL); + if (SUCCEEDED(hr)) { + ok(V_VT(&var) == VT_BSTR, "V_VT(var) = %d\n", V_VT(&var)); + if(!lstrcmpW(V_BSTR(&var), mrleW)) + have_mrle = TRUE; + VariantClear(&var); } } - if (prop_bag) - IPropertyBag_Release(prop_bag); + hr = IMoniker_BindToObject(moniker, bind_ctx, NULL, &IID_IUnknown, NULL); + ok(hr == E_POINTER, "got %#x\n", hr); + + IPropertyBag_Release(prop_bag); IMoniker_Release(moniker); } IEnumMoniker_Release(enum_moniker); @@ -224,7 +239,719 @@ static void test_moniker_isequal(void) return; } -/* CLSID_CDeviceMoniker */ +static BOOL find_moniker(const GUID *class, IMoniker *needle) +{ + ICreateDevEnum *devenum; + IEnumMoniker *enum_mon; + IMoniker *mon; + BOOL found = FALSE; + + CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, &IID_ICreateDevEnum, (void **)&devenum); + ICreateDevEnum_CreateClassEnumerator(devenum, class, &enum_mon, 0); + while (!found && IEnumMoniker_Next(enum_mon, 1, &mon, NULL) == S_OK) + { + if (IMoniker_IsEqual(mon, needle) == S_OK) + found = TRUE; + + IMoniker_Release(mon); + } + + IEnumMoniker_Release(enum_mon); + ICreateDevEnum_Release(devenum); + return found; +} + +DEFINE_GUID(CLSID_TestFilter, 0xdeadbeef,0xcf51,0x43e6,0xb6,0xc5,0x29,0x9e,0xa8,0xb6,0xb5,0x91); + +static void test_register_filter(void) +{ + static const WCHAR name[] = {'d','e','v','e','n','u','m',' ','t','e','s','t',0}; + IFilterMapper2 *mapper2; + IMoniker *mon = NULL; + REGFILTER2 rgf2 = {0}; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC, &IID_IFilterMapper2, (void **)&mapper2); + ok(hr == S_OK, "Failed to create FilterMapper2: %#x\n", hr); + + rgf2.dwVersion = 2; + rgf2.dwMerit = MERIT_UNLIKELY; + S2(U(rgf2)).cPins2 = 0; + + hr = IFilterMapper2_RegisterFilter(mapper2, &CLSID_TestFilter, name, &mon, NULL, NULL, &rgf2); + if (hr == E_ACCESSDENIED) + { + skip("Not enough permissions to register filters\n"); + IFilterMapper2_Release(mapper2); + return; + } + ok(hr == S_OK, "RegisterFilter failed: %#x\n", hr); + + ok(find_moniker(&CLSID_LegacyAmFilterCategory, mon), "filter should be registered\n"); + + hr = IFilterMapper2_UnregisterFilter(mapper2, NULL, NULL, &CLSID_TestFilter); + ok(hr == S_OK, "UnregisterFilter failed: %#x\n", hr); + + ok(!find_moniker(&CLSID_LegacyAmFilterCategory, mon), "filter should not be registered\n"); + IMoniker_Release(mon); + + mon = NULL; + hr = IFilterMapper2_RegisterFilter(mapper2, &CLSID_TestFilter, name, &mon, &CLSID_AudioRendererCategory, NULL, &rgf2); + ok(hr == S_OK, "RegisterFilter failed: %#x\n", hr); + + ok(find_moniker(&CLSID_AudioRendererCategory, mon), "filter should be registered\n"); + + hr = IFilterMapper2_UnregisterFilter(mapper2, &CLSID_AudioRendererCategory, NULL, &CLSID_TestFilter); + ok(hr == S_OK, "UnregisterFilter failed: %#x\n", hr); + + ok(!find_moniker(&CLSID_AudioRendererCategory, mon), "filter should not be registered\n"); + IMoniker_Release(mon); + + IFilterMapper2_Release(mapper2); +} + +static IMoniker *check_display_name_(int line, IParseDisplayName *parser, WCHAR *buffer) +{ + IMoniker *mon; + ULONG eaten; + HRESULT hr; + WCHAR *str; + + hr = IParseDisplayName_ParseDisplayName(parser, NULL, buffer, &eaten, &mon); + ok_(__FILE__, line)(hr == S_OK, "ParseDisplayName failed: %#x\n", hr); + + hr = IMoniker_GetDisplayName(mon, NULL, NULL, &str); + ok_(__FILE__, line)(hr == S_OK, "GetDisplayName failed: %#x\n", hr); + ok_(__FILE__, line)(!lstrcmpW(str, buffer), "got %s\n", wine_dbgstr_w(str)); + + CoTaskMemFree(str); + + return mon; +} +#define check_display_name(parser, buffer) check_display_name_(__LINE__, parser, buffer) + +static void test_directshow_filter(void) +{ + static const WCHAR instanceW[] = {'\\','I','n','s','t','a','n','c','e',0}; + static const WCHAR clsidW[] = {'C','L','S','I','D','\\',0}; + static WCHAR testW[] = {'\\','t','e','s','t',0}; + IParseDisplayName *parser; + IPropertyBag *prop_bag; + IMoniker *mon; + WCHAR buffer[200]; + LRESULT res; + VARIANT var; + HRESULT hr; + + /* Test ParseDisplayName and GetDisplayName */ + hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser); + ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr); + + lstrcpyW(buffer, deviceW); + lstrcatW(buffer, swW); + StringFromGUID2(&CLSID_AudioRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID); + lstrcatW(buffer, testW); + mon = check_display_name(parser, buffer); + + /* Test writing and reading from the property bag */ + ok(!find_moniker(&CLSID_AudioRendererCategory, mon), "filter should not be registered\n"); + + hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); + ok(hr == S_OK, "BindToStorage failed: %#x\n", hr); + + VariantInit(&var); + hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL); + ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got %#x\n", hr); + + /* writing causes the key to be created */ + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = SysAllocString(testW); + hr = IPropertyBag_Write(prop_bag, friendly_name, &var); + if (hr != E_ACCESSDENIED) + { + ok(hr == S_OK, "Write failed: %#x\n", hr); + + ok(find_moniker(&CLSID_AudioRendererCategory, mon), "filter should be registered\n"); + + VariantClear(&var); + hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL); + ok(hr == S_OK, "Read failed: %#x\n", hr); + ok(!lstrcmpW(V_BSTR(&var), testW), "got %s\n", wine_dbgstr_w(V_BSTR(&var))); + + IMoniker_Release(mon); + + /* devenum doesn't give us a way to unregister�we have to do that manually */ + lstrcpyW(buffer, clsidW); + StringFromGUID2(&CLSID_AudioRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID); + lstrcatW(buffer, instanceW); + lstrcatW(buffer, testW); + res = RegDeleteKeyW(HKEY_CLASSES_ROOT, buffer); + ok(!res, "RegDeleteKey failed: %lu\n", res); + } + + VariantClear(&var); + IPropertyBag_Release(prop_bag); + + /* name can be anything */ + + lstrcpyW(buffer, deviceW); + lstrcatW(buffer, swW); + lstrcatW(buffer, testW+1); + mon = check_display_name(parser, buffer); + + hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); + ok(hr == S_OK, "BindToStorage failed: %#x\n", hr); + + VariantClear(&var); + hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL); + ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got %#x\n", hr); + + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = SysAllocString(testW); + hr = IPropertyBag_Write(prop_bag, friendly_name, &var); + if (hr != E_ACCESSDENIED) + { + ok(hr == S_OK, "Write failed: %#x\n", hr); + + VariantClear(&var); + hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL); + ok(hr == S_OK, "Read failed: %#x\n", hr); + ok(!lstrcmpW(V_BSTR(&var), testW), "got %s\n", wine_dbgstr_w(V_BSTR(&var))); + + IMoniker_Release(mon); + + /* vista+ stores it inside the Instance key */ + RegDeleteKeyA(HKEY_CLASSES_ROOT, "CLSID\\test\\Instance"); + + res = RegDeleteKeyA(HKEY_CLASSES_ROOT, "CLSID\\test"); + ok(!res, "RegDeleteKey failed: %lu\n", res); + } + + VariantClear(&var); + IPropertyBag_Release(prop_bag); + IParseDisplayName_Release(parser); +} + +static void test_codec(void) +{ + static WCHAR testW[] = {'\\','t','e','s','t',0}; + IParseDisplayName *parser; + IPropertyBag *prop_bag; + IMoniker *mon; + WCHAR buffer[200]; + VARIANT var; + HRESULT hr; + + /* Test ParseDisplayName and GetDisplayName */ + hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser); + ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr); + + lstrcpyW(buffer, deviceW); + lstrcatW(buffer, cmW); + StringFromGUID2(&CLSID_AudioRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID); + lstrcatW(buffer, testW); + mon = check_display_name(parser, buffer); + + /* Test writing and reading from the property bag */ + ok(!find_moniker(&CLSID_AudioRendererCategory, mon), "codec should not be registered\n"); + + hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); + ok(hr == S_OK, "BindToStorage failed: %#x\n", hr); + + VariantInit(&var); + hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL); + ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got %#x\n", hr); + + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = SysAllocString(testW); + hr = IPropertyBag_Write(prop_bag, friendly_name, &var); + ok(hr == S_OK, "Write failed: %#x\n", hr); + + VariantClear(&var); + hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL); + ok(hr == S_OK, "Read failed: %#x\n", hr); + ok(!lstrcmpW(V_BSTR(&var), testW), "got %s\n", wine_dbgstr_w(V_BSTR(&var))); + + /* unlike DirectShow filters, these are automatically generated, so + * enumerating them will destroy the key */ + ok(!find_moniker(&CLSID_AudioRendererCategory, mon), "codec should not be registered\n"); + + hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL); + ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got %#x\n", hr); + + IPropertyBag_Release(prop_bag); + IMoniker_Release(mon); + + IParseDisplayName_Release(parser); +} + +static void test_legacy_filter(void) +{ + static const WCHAR nameW[] = {'t','e','s','t',0}; + IParseDisplayName *parser; + IPropertyBag *prop_bag; + IFilterMapper *mapper; + IMoniker *mon; + WCHAR buffer[200]; + VARIANT var; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser); + ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr); + + hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC, &IID_IFilterMapper, (void **)&mapper); + ok(hr == S_OK, "Failed to create FilterMapper: %#x\n", hr); + + hr = IFilterMapper_RegisterFilter(mapper, CLSID_TestFilter, nameW, 0xdeadbeef); + if (hr == VFW_E_BAD_KEY) + { + win_skip("not enough permissions to register filters\n"); + goto end; + } + ok(hr == S_OK, "RegisterFilter failed: %#x\n", hr); + + lstrcpyW(buffer, deviceW); + lstrcatW(buffer, cmW); + StringFromGUID2(&CLSID_LegacyAmFilterCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID); + lstrcatW(buffer, backslashW); + StringFromGUID2(&CLSID_TestFilter, buffer + lstrlenW(buffer), CHARS_IN_GUID); + + mon = check_display_name(parser, buffer); + ok(find_moniker(&CLSID_LegacyAmFilterCategory, mon), "filter should be registered\n"); + + hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); + ok(hr == S_OK, "BindToStorage failed: %#x\n", hr); + + VariantInit(&var); + hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL); + ok(hr == S_OK, "Read failed: %#x\n", hr); + + StringFromGUID2(&CLSID_TestFilter, buffer, CHARS_IN_GUID); + ok(!lstrcmpW(buffer, V_BSTR(&var)), "expected %s, got %s\n", + wine_dbgstr_w(buffer), wine_dbgstr_w(V_BSTR(&var))); + + VariantClear(&var); + hr = IPropertyBag_Read(prop_bag, clsidW, &var, NULL); + ok(hr == S_OK, "Read failed: %#x\n", hr); + ok(!lstrcmpW(buffer, V_BSTR(&var)), "expected %s, got %s\n", + wine_dbgstr_w(buffer), wine_dbgstr_w(V_BSTR(&var))); + + IPropertyBag_Release(prop_bag); + + hr = IFilterMapper_UnregisterFilter(mapper, CLSID_TestFilter); + ok(hr == S_OK, "UnregisterFilter failed: %#x\n", hr); + + ok(!find_moniker(&CLSID_LegacyAmFilterCategory, mon), "filter should not be registered\n"); + IMoniker_Release(mon); + +end: + IFilterMapper_Release(mapper); + IParseDisplayName_Release(parser); +} + +static BOOL CALLBACK test_dsound(GUID *guid, const WCHAR *desc, const WCHAR *module, void *context) +{ + static const WCHAR defaultW[] = {'D','e','f','a','u','l','t',' ','D','i','r','e','c','t','S','o','u','n','d',' ','D','e','v','i','c','e',0}; + static const WCHAR directsoundW[] = {'D','i','r','e','c','t','S','o','u','n','d',':',' ',0}; + static const WCHAR dsguidW[] = {'D','S','G','u','i','d',0}; + IParseDisplayName *parser; + IPropertyBag *prop_bag; + IMoniker *mon; + WCHAR buffer[200]; + WCHAR name[200]; + VARIANT var; + HRESULT hr; + + if (guid) + { + lstrcpyW(name, directsoundW); + lstrcatW(name, desc); + } + else + { + lstrcpyW(name, defaultW); + guid = (GUID *)&GUID_NULL; + } + + hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser); + ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr); + + lstrcpyW(buffer, deviceW); + lstrcatW(buffer, cmW); + StringFromGUID2(&CLSID_AudioRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID); + lstrcatW(buffer, backslashW); + lstrcatW(buffer, name); + + mon = check_display_name(parser, buffer); + + hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); + ok(hr == S_OK, "BindToStorage failed: %#x\n", hr); + + VariantInit(&var); + hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL); + if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) + { + /* Win8+ uses the GUID instead of the device name */ + IPropertyBag_Release(prop_bag); + IMoniker_Release(mon); + + lstrcpyW(buffer, deviceW); + lstrcatW(buffer, cmW); + StringFromGUID2(&CLSID_AudioRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID); + lstrcatW(buffer, backslashW); + lstrcatW(buffer, directsoundW); + StringFromGUID2(guid, buffer + lstrlenW(buffer) - 1, CHARS_IN_GUID); + + mon = check_display_name(parser, buffer); + + hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); + ok(hr == S_OK, "BindToStorage failed: %#x\n", hr); + + VariantInit(&var); + hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL); + } + ok(hr == S_OK, "Read failed: %#x\n", hr); + + ok(!lstrcmpW(name, V_BSTR(&var)), "expected %s, got %s\n", + wine_dbgstr_w(name), wine_dbgstr_w(V_BSTR(&var))); + + VariantClear(&var); + hr = IPropertyBag_Read(prop_bag, clsidW, &var, NULL); + ok(hr == S_OK, "Read failed: %#x\n", hr); + + StringFromGUID2(&CLSID_DSoundRender, buffer, CHARS_IN_GUID); + ok(!lstrcmpW(buffer, V_BSTR(&var)), "expected %s, got %s\n", + wine_dbgstr_w(buffer), wine_dbgstr_w(V_BSTR(&var))); + + VariantClear(&var); + hr = IPropertyBag_Read(prop_bag, dsguidW, &var, NULL); + ok(hr == S_OK, "Read failed: %#x\n", hr); + + StringFromGUID2(guid, buffer, CHARS_IN_GUID); + ok(!lstrcmpW(buffer, V_BSTR(&var)), "expected %s, got %s\n", + wine_dbgstr_w(buffer), wine_dbgstr_w(V_BSTR(&var))); + + IPropertyBag_Release(prop_bag); + IMoniker_Release(mon); + IParseDisplayName_Release(parser); + return TRUE; +} + +static void test_waveout(void) +{ + static const WCHAR defaultW[] = {'D','e','f','a','u','l','t',' ','W','a','v','e','O','u','t',' ','D','e','v','i','c','e',0}; + static const WCHAR waveoutidW[] = {'W','a','v','e','O','u','t','I','d',0}; + IParseDisplayName *parser; + IPropertyBag *prop_bag; + IMoniker *mon; + WCHAR endpoint[200]; + WAVEOUTCAPSW caps; + WCHAR buffer[200]; + const WCHAR *name; + MMRESULT mmr; + int count, i; + VARIANT var; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser); + ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr); + + count = waveOutGetNumDevs(); + + for (i = -1; i < count; i++) + { + waveOutGetDevCapsW(i, &caps, sizeof(caps)); + + if (i == -1) /* WAVE_MAPPER */ + name = defaultW; + else + name = caps.szPname; + + lstrcpyW(buffer, deviceW); + lstrcatW(buffer, cmW); + StringFromGUID2(&CLSID_AudioRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID); + lstrcatW(buffer, backslashW); + lstrcatW(buffer, name); + + mon = check_display_name(parser, buffer); + + hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); + ok(hr == S_OK, "BindToStorage failed: %#x\n", hr); + + VariantInit(&var); + hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL); + if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) + { + IPropertyBag_Release(prop_bag); + IMoniker_Release(mon); + + /* Win8+ uses the endpoint GUID instead of the device name */ + mmr = waveOutMessage((HWAVEOUT)(DWORD_PTR) i, DRV_QUERYFUNCTIONINSTANCEID, + (DWORD_PTR) endpoint, sizeof(endpoint)); + ok(!mmr, "waveOutMessage failed: %u\n", mmr); + + lstrcpyW(buffer, deviceW); + lstrcatW(buffer, cmW); + StringFromGUID2(&CLSID_AudioRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID); + lstrcatW(buffer, backslashW); + lstrcatW(buffer, waveW); + lstrcatW(buffer, strchrW(endpoint, '}') + 2); + + mon = check_display_name(parser, buffer); + + hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); + ok(hr == S_OK, "BindToStorage failed: %#x\n", hr); + + hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL); + } + ok(hr == S_OK, "Read failed: %#x\n", hr); + + ok(!strncmpW(name, V_BSTR(&var), lstrlenW(name)), "expected %s, got %s\n", + wine_dbgstr_w(name), wine_dbgstr_w(V_BSTR(&var))); + + VariantClear(&var); + hr = IPropertyBag_Read(prop_bag, clsidW, &var, NULL); + ok(hr == S_OK, "Read failed: %#x\n", hr); + + StringFromGUID2(&CLSID_AudioRender, buffer, CHARS_IN_GUID); + ok(!lstrcmpW(buffer, V_BSTR(&var)), "expected %s, got %s\n", + wine_dbgstr_w(buffer), wine_dbgstr_w(V_BSTR(&var))); + + VariantClear(&var); + hr = IPropertyBag_Read(prop_bag, waveoutidW, &var, NULL); + ok(hr == S_OK, "Read failed: %#x\n", hr); + + ok(V_I4(&var) == i, "expected %d, got %d\n", i, V_I4(&var)); + + IPropertyBag_Release(prop_bag); + IMoniker_Release(mon); + } + + IParseDisplayName_Release(parser); +} + +static void test_wavein(void) +{ + static const WCHAR waveinidW[] = {'W','a','v','e','I','n','I','d',0}; + IParseDisplayName *parser; + IPropertyBag *prop_bag; + IMoniker *mon; + WCHAR endpoint[200]; + WCHAR buffer[200]; + WAVEINCAPSW caps; + MMRESULT mmr; + int count, i; + VARIANT var; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser); + ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr); + + count = waveInGetNumDevs(); + + for (i = 0; i < count; i++) + { + waveInGetDevCapsW(i, &caps, sizeof(caps)); + + lstrcpyW(buffer, deviceW); + lstrcatW(buffer, cmW); + StringFromGUID2(&CLSID_AudioInputDeviceCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID); + lstrcatW(buffer, backslashW); + lstrcatW(buffer, caps.szPname); + + mon = check_display_name(parser, buffer); + + hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); + ok(hr == S_OK, "BindToStorage failed: %#x\n", hr); + + VariantInit(&var); + hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL); + if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) + { + IPropertyBag_Release(prop_bag); + IMoniker_Release(mon); + + /* Win8+ uses the endpoint GUID instead of the device name */ + mmr = waveInMessage((HWAVEIN)(DWORD_PTR) i, DRV_QUERYFUNCTIONINSTANCEID, + (DWORD_PTR) endpoint, sizeof(endpoint)); + ok(!mmr, "waveInMessage failed: %u\n", mmr); + + lstrcpyW(buffer, deviceW); + lstrcatW(buffer, cmW); + StringFromGUID2(&CLSID_AudioInputDeviceCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID); + lstrcatW(buffer, backslashW); + lstrcatW(buffer, waveW); + lstrcatW(buffer, strchrW(endpoint, '}') + 2); + + mon = check_display_name(parser, buffer); + + hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); + ok(hr == S_OK, "BindToStorage failed: %#x\n", hr); + + hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL); + } + ok(hr == S_OK, "Read failed: %#x\n", hr); + + ok(!strncmpW(caps.szPname, V_BSTR(&var), lstrlenW(caps.szPname)), "expected %s, got %s\n", + wine_dbgstr_w(caps.szPname), wine_dbgstr_w(V_BSTR(&var))); + + VariantClear(&var); + hr = IPropertyBag_Read(prop_bag, clsidW, &var, NULL); + ok(hr == S_OK, "Read failed: %#x\n", hr); + + StringFromGUID2(&CLSID_AudioRecord, buffer, CHARS_IN_GUID); + ok(!lstrcmpW(buffer, V_BSTR(&var)), "expected %s, got %s\n", + wine_dbgstr_w(buffer), wine_dbgstr_w(V_BSTR(&var))); + + VariantClear(&var); + hr = IPropertyBag_Read(prop_bag, waveinidW, &var, NULL); + ok(hr == S_OK, "Read failed: %#x\n", hr); + + ok(V_I4(&var) == i, "expected %d, got %d\n", i, V_I4(&var)); + + IPropertyBag_Release(prop_bag); + IMoniker_Release(mon); + } + + IParseDisplayName_Release(parser); +} + +static void test_midiout(void) +{ + static const WCHAR defaultW[] = {'D','e','f','a','u','l','t',' ','M','i','d','i','O','u','t',' ','D','e','v','i','c','e',0}; + static const WCHAR midioutidW[] = {'M','i','d','i','O','u','t','I','d',0}; + IParseDisplayName *parser; + IPropertyBag *prop_bag; + IMoniker *mon; + MIDIOUTCAPSW caps; + WCHAR buffer[200]; + const WCHAR *name; + int count, i; + VARIANT var; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser); + ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr); + + count = midiOutGetNumDevs(); + + for (i = -1; i < count; i++) + { + midiOutGetDevCapsW(i, &caps, sizeof(caps)); + + if (i == -1) /* MIDI_MAPPER */ + name = defaultW; + else + name = caps.szPname; + + lstrcpyW(buffer, deviceW); + lstrcatW(buffer, cmW); + StringFromGUID2(&CLSID_MidiRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID); + lstrcatW(buffer, backslashW); + lstrcatW(buffer, name); + + mon = check_display_name(parser, buffer); + + hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); + ok(hr == S_OK, "BindToStorage failed: %#x\n", hr); + + VariantInit(&var); + hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL); + ok(hr == S_OK, "Read failed: %#x\n", hr); + + ok(!lstrcmpW(name, V_BSTR(&var)), "expected %s, got %s\n", + wine_dbgstr_w(name), wine_dbgstr_w(V_BSTR(&var))); + + VariantClear(&var); + hr = IPropertyBag_Read(prop_bag, clsidW, &var, NULL); + ok(hr == S_OK, "Read failed: %#x\n", hr); + + StringFromGUID2(&CLSID_AVIMIDIRender, buffer, CHARS_IN_GUID); + ok(!lstrcmpW(buffer, V_BSTR(&var)), "expected %s, got %s\n", + wine_dbgstr_w(buffer), wine_dbgstr_w(V_BSTR(&var))); + + VariantClear(&var); + hr = IPropertyBag_Read(prop_bag, midioutidW, &var, NULL); + ok(hr == S_OK, "Read failed: %#x\n", hr); + + ok(V_I4(&var) == i, "expected %d, got %d\n", i, V_I4(&var)); + + IPropertyBag_Release(prop_bag); + IMoniker_Release(mon); + } + + IParseDisplayName_Release(parser); +} + +static void test_vfw(void) +{ + static const WCHAR fcchandlerW[] = {'F','c','c','H','a','n','d','l','e','r',0}; + IParseDisplayName *parser; + IPropertyBag *prop_bag; + IMoniker *mon; + WCHAR buffer[200]; + ICINFO info; + VARIANT var; + HRESULT hr; + int i = 0; + HIC hic; + + if (broken(sizeof(void *) == 8)) + { + win_skip("VFW codecs are not enumerated on 64-bit Windows\n"); + return; + } + + hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser); + ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr); + + while (ICInfo(ICTYPE_VIDEO, i++, &info)) + { + WCHAR name[5] = {LOBYTE(LOWORD(info.fccHandler)), HIBYTE(LOWORD(info.fccHandler)), + LOBYTE(HIWORD(info.fccHandler)), HIBYTE(HIWORD(info.fccHandler))}; + + hic = ICOpen(ICTYPE_VIDEO, info.fccHandler, ICMODE_QUERY); + ICGetInfo(hic, &info, sizeof(info)); + ICClose(hic); + + lstrcpyW(buffer, deviceW); + lstrcatW(buffer, cmW); + StringFromGUID2(&CLSID_VideoCompressorCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID); + lstrcatW(buffer, backslashW); + lstrcatW(buffer, name); + + mon = check_display_name(parser, buffer); + + hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); + ok(hr == S_OK, "BindToStorage failed: %#x\n", hr); + + VariantInit(&var); + hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL); + ok(hr == S_OK, "Read failed: %#x\n", hr); + + ok(!lstrcmpW(info.szDescription, V_BSTR(&var)), "expected %s, got %s\n", + wine_dbgstr_w(info.szDescription), wine_dbgstr_w(V_BSTR(&var))); + + VariantClear(&var); + hr = IPropertyBag_Read(prop_bag, clsidW, &var, NULL); + ok(hr == S_OK, "Read failed: %#x\n", hr); + + StringFromGUID2(&CLSID_AVICo, buffer, CHARS_IN_GUID); + ok(!lstrcmpW(buffer, V_BSTR(&var)), "expected %s, got %s\n", + wine_dbgstr_w(buffer), wine_dbgstr_w(V_BSTR(&var))); + + VariantClear(&var); + hr = IPropertyBag_Read(prop_bag, fcchandlerW, &var, NULL); + ok(hr == S_OK, "Read failed: %#x\n", hr); + ok(!lstrcmpW(name, V_BSTR(&var)), "expected %s, got %s\n", + wine_dbgstr_w(name), wine_dbgstr_w(V_BSTR(&var))); + + IPropertyBag_Release(prop_bag); + IMoniker_Release(mon); + } + + IParseDisplayName_Release(parser); +} START_TEST(devenum) { @@ -244,6 +971,17 @@ START_TEST(devenum) } test_moniker_isequal(); + test_register_filter(); + test_directshow_filter(); + test_codec(); + + test_legacy_filter(); + hr = DirectSoundEnumerateW(test_dsound, NULL); + ok(hr == S_OK, "got %#x\n", hr); + test_waveout(); + test_wavein(); + test_midiout(); + test_vfw(); CoUninitialize(); }
6 years, 7 months
1
0
0
0
01/01: [DEVENUM] Sync with Wine Staging 3.9. CORE-14656
by Amine Khaldi
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5e3341f4bb252ed7127a7…
commit 5e3341f4bb252ed7127a7439bf6a90e73f0f6295 Author: Amine Khaldi <amine.khaldi(a)reactos.org> AuthorDate: Sun May 27 03:56:13 2018 +0100 Commit: Amine Khaldi <amine.khaldi(a)reactos.org> CommitDate: Sun May 27 03:56:13 2018 +0100 [DEVENUM] Sync with Wine Staging 3.9. CORE-14656 --- dll/directx/wine/devenum/CMakeLists.txt | 4 +- dll/directx/wine/devenum/createdevenum.c | 1169 ++++++++++++++------------- dll/directx/wine/devenum/devenum.rc | 12 - dll/directx/wine/devenum/devenum_private.h | 40 +- dll/directx/wine/devenum/fil_data.idl | 47 ++ dll/directx/wine/devenum/mediacatenum.c | 214 +++-- dll/directx/wine/devenum/parsedisplayname.c | 93 +-- media/doc/README.WINE | 2 +- 8 files changed, 859 insertions(+), 722 deletions(-) diff --git a/dll/directx/wine/devenum/CMakeLists.txt b/dll/directx/wine/devenum/CMakeLists.txt index d8af794b86..1f5e7eb321 100644 --- a/dll/directx/wine/devenum/CMakeLists.txt +++ b/dll/directx/wine/devenum/CMakeLists.txt @@ -4,6 +4,7 @@ add_definitions(-D_WIN32_WINNT=0x600 -DWINVER=0x600) add_definitions(-D__WINESRC__) include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine) +add_idl_headers(devenum_fil_data_header fil_data.idl) spec2def(devenum.dll devenum.spec) list(APPEND SOURCE @@ -23,6 +24,7 @@ set_source_files_properties(devenum.rc PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT set_module_type(devenum win32dll UNICODE) target_link_libraries(devenum strmiids uuid wine) add_delay_importlibs(devenum msvfw32) -add_importlibs(devenum advapi32 advapi32_vista ole32 oleaut32 winmm user32 avicap32 msacm32 msvcrt kernel32 ntdll) +add_importlibs(devenum advapi32 advapi32_vista ole32 oleaut32 winmm user32 avicap32 msacm32 dsound msvcrt kernel32 ntdll) +add_dependencies(devenum devenum_fil_data_header) add_pch(devenum precomp.h SOURCE) add_cd_file(TARGET devenum DESTINATION reactos/system32 FOR all) diff --git a/dll/directx/wine/devenum/createdevenum.c b/dll/directx/wine/devenum/createdevenum.c index 002ffbc876..fbde0cb61d 100644 --- a/dll/directx/wine/devenum/createdevenum.c +++ b/dll/directx/wine/devenum/createdevenum.c @@ -29,22 +29,20 @@ #include "devenum_private.h" #include "vfw.h" #include "aviriff.h" +#include "dsound.h" #include "wine/debug.h" #include "wine/unicode.h" +#include "wine/heap.h" #include "mmddk.h" +#include "initguid.h" +#include "fil_data.h" + WINE_DEFAULT_DEBUG_CHANNEL(devenum); extern HINSTANCE DEVENUM_hInstance; -const WCHAR wszInstanceKeyName[] ={'\\','I','n','s','t','a','n','c','e',0}; - -static const WCHAR wszRegSeparator[] = {'\\', 0 }; -static const WCHAR wszActiveMovieKey[] = {'S','o','f','t','w','a','r','e','\\', - 'M','i','c','r','o','s','o','f','t','\\', - 'A','c','t','i','v','e','M','o','v','i','e','\\', - 'd','e','v','e','n','u','m','\\',0}; static const WCHAR wszFilterKeyName[] = {'F','i','l','t','e','r',0}; static const WCHAR wszMeritName[] = {'M','e','r','i','t',0}; static const WCHAR wszPins[] = {'P','i','n','s',0}; @@ -54,11 +52,11 @@ static const WCHAR wszDirection[] = {'D','i','r','e','c','t','i','o','n',0}; static const WCHAR wszIsRendered[] = {'I','s','R','e','n','d','e','r','e','d',0}; static const WCHAR wszTypes[] = {'T','y','p','e','s',0}; static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0}; -static const WCHAR wszWaveInID[] = {'W','a','v','e','I','n','I','D',0}; -static const WCHAR wszWaveOutID[] = {'W','a','v','e','O','u','t','I','D',0}; +static const WCHAR wszFilterData[] = {'F','i','l','t','e','r','D','a','t','a',0}; static ULONG WINAPI DEVENUM_ICreateDevEnum_AddRef(ICreateDevEnum * iface); -static HRESULT DEVENUM_CreateSpecialCategories(void); +static HRESULT register_codecs(void); +static HRESULT DEVENUM_CreateAMCategoryKey(const CLSID * clsidCategory); /********************************************************************** * DEVENUM_ICreateDevEnum_QueryInterface (also IUnknown) @@ -108,87 +106,37 @@ static ULONG WINAPI DEVENUM_ICreateDevEnum_Release(ICreateDevEnum * iface) return 1; /* non-heap based object */ } -static BOOL IsSpecialCategory(const CLSID *clsid) +static HRESULT register_codec(const CLSID *class, const WCHAR *name, IMoniker **ret) { - return IsEqualGUID(clsid, &CLSID_AudioRendererCategory) || - IsEqualGUID(clsid, &CLSID_AudioInputDeviceCategory) || - IsEqualGUID(clsid, &CLSID_VideoInputDeviceCategory) || - IsEqualGUID(clsid, &CLSID_VideoCompressorCategory) || - IsEqualGUID(clsid, &CLSID_AudioCompressorCategory) || - IsEqualGUID(clsid, &CLSID_MidiRendererCategory); -} + static const WCHAR deviceW[] = {'@','d','e','v','i','c','e',':','c','m',':',0}; + IParseDisplayName *parser; + WCHAR *buffer; + ULONG eaten; + HRESULT hr; -HRESULT DEVENUM_GetCategoryKey(REFCLSID clsidDeviceClass, HKEY *pBaseKey, WCHAR *wszRegKeyName, UINT maxLen) -{ - if (IsSpecialCategory(clsidDeviceClass)) - { - *pBaseKey = HKEY_CURRENT_USER; - strcpyW(wszRegKeyName, wszActiveMovieKey); + hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser); + if (FAILED(hr)) + return hr; - if (!StringFromGUID2(clsidDeviceClass, wszRegKeyName + strlenW(wszRegKeyName), maxLen - strlenW(wszRegKeyName))) - return E_OUTOFMEMORY; - } - else + buffer = heap_alloc((strlenW(deviceW) + CHARS_IN_GUID + strlenW(name) + 1) * sizeof(WCHAR)); + if (!buffer) { - *pBaseKey = HKEY_CLASSES_ROOT; - strcpyW(wszRegKeyName, clsid_keyname); - strcatW(wszRegKeyName, wszRegSeparator); - - if (!StringFromGUID2(clsidDeviceClass, wszRegKeyName + CLSID_STR_LEN, maxLen - CLSID_STR_LEN)) - return E_OUTOFMEMORY; - - strcatW(wszRegKeyName, wszInstanceKeyName); - } - - return S_OK; -} - -static HKEY open_category_key(const CLSID *clsid) -{ - WCHAR key_name[sizeof(wszInstanceKeyName)/sizeof(WCHAR) + CHARS_IN_GUID-1 + 6 /* strlen("CLSID\") */], *ptr; - HKEY ret; - - strcpyW(key_name, clsid_keyname); - ptr = key_name + strlenW(key_name); - *ptr++ = '\\'; - - if (!StringFromGUID2(clsid, ptr, CHARS_IN_GUID)) - return NULL; - - ptr += strlenW(ptr); - strcpyW(ptr, wszInstanceKeyName); - - if (RegOpenKeyExW(HKEY_CLASSES_ROOT, key_name, 0, KEY_READ, &ret) != ERROR_SUCCESS) { - WARN("Could not open %s\n", debugstr_w(key_name)); - return NULL; + IParseDisplayName_Release(parser); + return E_OUTOFMEMORY; } - return ret; -} - -static HKEY open_special_category_key(const CLSID *clsid, BOOL create) -{ - WCHAR key_name[sizeof(wszActiveMovieKey)/sizeof(WCHAR) + CHARS_IN_GUID-1]; - HKEY ret; - LONG res; - - strcpyW(key_name, wszActiveMovieKey); - if (!StringFromGUID2(clsid, key_name + sizeof(wszActiveMovieKey)/sizeof(WCHAR)-1, CHARS_IN_GUID)) - return NULL; + strcpyW(buffer, deviceW); + StringFromGUID2(class, buffer + strlenW(buffer), CHARS_IN_GUID); + strcatW(buffer, backslashW); + strcatW(buffer, name); - if(create) - res = RegCreateKeyW(HKEY_CURRENT_USER, key_name, &ret); - else - res = RegOpenKeyExW(HKEY_CURRENT_USER, key_name, 0, KEY_READ, &ret); - if (res != ERROR_SUCCESS) { - WARN("Could not open %s\n", debugstr_w(key_name)); - return NULL; - } - - return ret; + hr = IParseDisplayName_ParseDisplayName(parser, NULL, buffer, &eaten, ret); + IParseDisplayName_Release(parser); + heap_free(buffer); + return hr; } -static void DEVENUM_ReadPinTypes(HKEY hkeyPinKey, REGFILTERPINS *rgPin) +static void DEVENUM_ReadPinTypes(HKEY hkeyPinKey, REGFILTERPINS2 *rgPin) { HKEY hkeyTypes = NULL; DWORD dwMajorTypes, i; @@ -285,7 +233,11 @@ static void DEVENUM_ReadPins(HKEY hkeyFilterClass, REGFILTER2 *rgf2) { HKEY hkeyPins = NULL; DWORD dwPinsSubkeys, i; - REGFILTERPINS *rgPins = NULL; + REGFILTERPINS2 *rgPins = NULL; + + rgf2->dwVersion = 2; + rgf2->u.s2.cPins2 = 0; + rgf2->u.s2.rgPins2 = NULL; if (RegOpenKeyExW(hkeyFilterClass, wszPins, 0, KEY_READ, &hkeyPins) != ERROR_SUCCESS) return ; @@ -299,7 +251,7 @@ static void DEVENUM_ReadPins(HKEY hkeyFilterClass, REGFILTER2 *rgf2) if (dwPinsSubkeys) { - rgPins = CoTaskMemAlloc(sizeof(REGFILTERPINS) * dwPinsSubkeys); + rgPins = CoTaskMemAlloc(sizeof(REGFILTERPINS2) * dwPinsSubkeys); if (!rgPins) { RegCloseKey(hkeyPins); @@ -312,82 +264,137 @@ static void DEVENUM_ReadPins(HKEY hkeyFilterClass, REGFILTER2 *rgf2) HKEY hkeyPinKey = NULL; WCHAR wszPinName[MAX_PATH]; DWORD cName = sizeof(wszPinName) / sizeof(WCHAR); - DWORD Type, cbData; - REGFILTERPINS *rgPin = &rgPins[rgf2->u.s1.cPins]; + REGFILTERPINS2 *rgPin = &rgPins[rgf2->u.s2.cPins2]; + DWORD value, size, Type; LONG lRet; - rgPin->strName = NULL; - rgPin->clsConnectsToFilter = &GUID_NULL; - rgPin->strConnectsToPin = NULL; - rgPin->nMediaTypes = 0; - rgPin->lpMediaType = NULL; + memset(rgPin, 0, sizeof(*rgPin)); if (RegEnumKeyExW(hkeyPins, i, wszPinName, &cName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) continue; if (RegOpenKeyExW(hkeyPins, wszPinName, 0, KEY_READ, &hkeyPinKey) != ERROR_SUCCESS) continue; - rgPin->strName = CoTaskMemAlloc((strlenW(wszPinName) + 1) * sizeof(WCHAR)); - if (!rgPin->strName) goto error_cleanup; - - strcpyW(rgPin->strName, wszPinName); - - cbData = sizeof(rgPin->bMany); - lRet = RegQueryValueExW(hkeyPinKey, wszAllowedMany, NULL, &Type, (LPBYTE)&rgPin->bMany, &cbData); + size = sizeof(DWORD); + lRet = RegQueryValueExW(hkeyPinKey, wszAllowedMany, NULL, &Type, (BYTE *)&value, &size); if (lRet != ERROR_SUCCESS || Type != REG_DWORD) goto error_cleanup; + if (value) + rgPin->dwFlags |= REG_PINFLAG_B_MANY; - cbData = sizeof(rgPin->bZero); - lRet = RegQueryValueExW(hkeyPinKey, wszAllowedZero, NULL, &Type, (LPBYTE)&rgPin->bZero, &cbData); + size = sizeof(DWORD); + lRet = RegQueryValueExW(hkeyPinKey, wszAllowedZero, NULL, &Type, (BYTE *)&value, &size); if (lRet != ERROR_SUCCESS || Type != REG_DWORD) goto error_cleanup; + if (value) + rgPin->dwFlags |= REG_PINFLAG_B_ZERO; - cbData = sizeof(rgPin->bOutput); - lRet = RegQueryValueExW(hkeyPinKey, wszDirection, NULL, &Type, (LPBYTE)&rgPin->bOutput, &cbData); + size = sizeof(DWORD); + lRet = RegQueryValueExW(hkeyPinKey, wszDirection, NULL, &Type, (BYTE *)&value, &size); if (lRet != ERROR_SUCCESS || Type != REG_DWORD) goto error_cleanup; + if (value) + rgPin->dwFlags |= REG_PINFLAG_B_OUTPUT; + - cbData = sizeof(rgPin->bRendered); - lRet = RegQueryValueExW(hkeyPinKey, wszIsRendered, NULL, &Type, (LPBYTE)&rgPin->bRendered, &cbData); + size = sizeof(DWORD); + lRet = RegQueryValueExW(hkeyPinKey, wszIsRendered, NULL, &Type, (BYTE *)&value, &size); if (lRet != ERROR_SUCCESS || Type != REG_DWORD) goto error_cleanup; + if (value) + rgPin->dwFlags |= REG_PINFLAG_B_RENDERER; DEVENUM_ReadPinTypes(hkeyPinKey, rgPin); - ++rgf2->u.s1.cPins; + ++rgf2->u.s2.cPins2; continue; error_cleanup: RegCloseKey(hkeyPinKey); - CoTaskMemFree(rgPin->strName); } RegCloseKey(hkeyPins); - if (rgPins && !rgf2->u.s1.cPins) + if (rgPins && !rgf2->u.s2.cPins2) { CoTaskMemFree(rgPins); rgPins = NULL; } - rgf2->u.s1.rgPins = rgPins; + rgf2->u.s2.rgPins2 = rgPins; +} + +static void free_regfilter2(REGFILTER2 *rgf) +{ + if (rgf->u.s2.rgPins2) + { + UINT iPin; + + for (iPin = 0; iPin < rgf->u.s2.cPins2; iPin++) + { + if (rgf->u.s2.rgPins2[iPin].lpMediaType) + { + UINT iType; + + for (iType = 0; iType < rgf->u.s2.rgPins2[iPin].nMediaTypes; iType++) + { + CoTaskMemFree((void *)rgf->u.s2.rgPins2[iPin].lpMediaType[iType].clsMajorType); + CoTaskMemFree((void *)rgf->u.s2.rgPins2[iPin].lpMediaType[iType].clsMinorType); + } + + CoTaskMemFree((void *)rgf->u.s2.rgPins2[iPin].lpMediaType); + } + } + + CoTaskMemFree((void *)rgf->u.s2.rgPins2); + } +} + +static void write_filter_data(IPropertyBag *prop_bag, REGFILTER2 *rgf) +{ + IAMFilterData *fildata; + SAFEARRAYBOUND sabound; + BYTE *data, *array; + VARIANT var; + ULONG size; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC, &IID_IAMFilterData, (void **)&fildata); + if (FAILED(hr)) goto cleanup; + + hr = IAMFilterData_CreateFilterData(fildata, rgf, &data, &size); + if (FAILED(hr)) goto cleanup; + + V_VT(&var) = VT_ARRAY | VT_UI1; + sabound.lLbound = 0; + sabound.cElements = size; + if (!(V_ARRAY(&var) = SafeArrayCreate(VT_UI1, 1, &sabound))) + goto cleanup; + hr = SafeArrayAccessData(V_ARRAY(&var), (void *)&array); + if (FAILED(hr)) goto cleanup; + + memcpy(array, data, size); + hr = SafeArrayUnaccessData(V_ARRAY(&var)); + if (FAILED(hr)) goto cleanup; + + hr = IPropertyBag_Write(prop_bag, wszFilterData, &var); + if (FAILED(hr)) goto cleanup; + +cleanup: + VariantClear(&var); + CoTaskMemFree(data); + IAMFilterData_Release(fildata); } -static HRESULT DEVENUM_RegisterLegacyAmFilters(void) +static void register_legacy_filters(void) { HKEY hkeyFilter = NULL; DWORD dwFilterSubkeys, i; LONG lRet; - IFilterMapper2 *pMapper = NULL; HRESULT hr; - hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC, - &IID_IFilterMapper2, (void **) &pMapper); - if (SUCCEEDED(hr)) - { - lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszFilterKeyName, 0, KEY_READ, &hkeyFilter); - hr = HRESULT_FROM_WIN32(lRet); - } + lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszFilterKeyName, 0, KEY_READ, &hkeyFilter); + hr = HRESULT_FROM_WIN32(lRet); if (SUCCEEDED(hr)) { @@ -395,113 +402,487 @@ static HRESULT DEVENUM_RegisterLegacyAmFilters(void) hr = HRESULT_FROM_WIN32(lRet); } + if (SUCCEEDED(hr)) + hr = DEVENUM_CreateAMCategoryKey(&CLSID_LegacyAmFilterCategory); + if (SUCCEEDED(hr)) { for (i = 0; i < dwFilterSubkeys; i++) { WCHAR wszFilterSubkeyName[64]; DWORD cName = sizeof(wszFilterSubkeyName) / sizeof(WCHAR); - HKEY hkeyCategoryBaseKey; + IPropertyBag *prop_bag = NULL; WCHAR wszRegKey[MAX_PATH]; - HKEY hkeyInstance = NULL; + HKEY classkey = NULL; + IMoniker *mon = NULL; + VARIANT var; + REGFILTER2 rgf2; + DWORD Type, len; if (RegEnumKeyExW(hkeyFilter, i, wszFilterSubkeyName, &cName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) continue; - hr = DEVENUM_GetCategoryKey(&CLSID_LegacyAmFilterCategory, &hkeyCategoryBaseKey, wszRegKey, MAX_PATH); - if (FAILED(hr)) continue; + TRACE("Registering %s\n", debugstr_w(wszFilterSubkeyName)); - strcatW(wszRegKey, wszRegSeparator); + strcpyW(wszRegKey, clsidW); strcatW(wszRegKey, wszFilterSubkeyName); - if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszRegKey, 0, KEY_READ, &hkeyInstance) == ERROR_SUCCESS) + if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszRegKey, 0, KEY_READ, &classkey) != ERROR_SUCCESS) + continue; + + hr = register_codec(&CLSID_LegacyAmFilterCategory, wszFilterSubkeyName, &mon); + if (FAILED(hr)) goto cleanup; + + hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); + if (FAILED(hr)) goto cleanup; + + /* write friendly name */ + len = 0; + V_VT(&var) = VT_BSTR; + if (!RegQueryValueExW(classkey, NULL, NULL, &Type, NULL, &len)) { - RegCloseKey(hkeyInstance); + WCHAR *friendlyname = heap_alloc(len); + if (!friendlyname) + goto cleanup; + RegQueryValueExW(classkey, NULL, NULL, &Type, (BYTE *)friendlyname, &len); + V_BSTR(&var) = SysAllocStringLen(friendlyname, len/sizeof(WCHAR)); + heap_free(friendlyname); } else - { - /* Filter is registered the IFilterMapper(1)-way in HKCR\Filter. Needs to be added to - * legacy am filter category. */ - HKEY hkeyFilterClass = NULL; - REGFILTER2 rgf2; - CLSID clsidFilter; - WCHAR wszFilterName[MAX_PATH]; - DWORD Type; - DWORD cbData; - HRESULT res; - IMoniker *pMoniker = NULL; - - TRACE("Registering %s\n", debugstr_w(wszFilterSubkeyName)); - - strcpyW(wszRegKey, clsid_keyname); - strcatW(wszRegKey, wszRegSeparator); - strcatW(wszRegKey, wszFilterSubkeyName); - - if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszRegKey, 0, KEY_READ, &hkeyFilterClass) != ERROR_SUCCESS) - continue; - - rgf2.dwVersion = 1; - rgf2.dwMerit = 0; - rgf2.u.s1.cPins = 0; - rgf2.u.s1.rgPins = NULL; - - cbData = sizeof(wszFilterName); - if (RegQueryValueExW(hkeyFilterClass, NULL, NULL, &Type, (LPBYTE)wszFilterName, &cbData) != ERROR_SUCCESS || - Type != REG_SZ) - goto cleanup; + V_BSTR(&var) = SysAllocString(wszFilterSubkeyName); + + if (!V_BSTR(&var)) + goto cleanup; + hr = IPropertyBag_Write(prop_bag, wszFriendlyName, &var); + if (FAILED(hr)) goto cleanup; + VariantClear(&var); + + /* write clsid */ + V_VT(&var) = VT_BSTR; + if (!(V_BSTR(&var) = SysAllocString(wszFilterSubkeyName))) + goto cleanup; + hr = IPropertyBag_Write(prop_bag, clsid_keyname, &var); + if (FAILED(hr)) goto cleanup; + VariantClear(&var); + + /* write filter data */ + rgf2.dwMerit = MERIT_NORMAL; + + len = sizeof(rgf2.dwMerit); + RegQueryValueExW(classkey, wszMeritName, NULL, &Type, (BYTE *)&rgf2.dwMerit, &len); + + DEVENUM_ReadPins(classkey, &rgf2); + + write_filter_data(prop_bag, &rgf2); + +cleanup: + if (prop_bag) IPropertyBag_Release(prop_bag); + if (mon) IMoniker_Release(mon); + RegCloseKey(classkey); + VariantClear(&var); + free_regfilter2(&rgf2); + } + } - cbData = sizeof(rgf2.dwMerit); - if (RegQueryValueExW(hkeyFilterClass, wszMeritName, NULL, &Type, (LPBYTE)&rgf2.dwMerit, &cbData) != ERROR_SUCCESS || - Type != REG_DWORD) - goto cleanup; + if (hkeyFilter) RegCloseKey(hkeyFilter); +} - DEVENUM_ReadPins(hkeyFilterClass, &rgf2); +static BOOL CALLBACK register_dsound_devices(GUID *guid, const WCHAR *desc, const WCHAR *module, void *context) +{ + static const WCHAR defaultW[] = {'D','e','f','a','u','l','t',' ','D','i','r','e','c','t','S','o','u','n','d',' ','D','e','v','i','c','e',0}; + static const WCHAR directsoundW[] = {'D','i','r','e','c','t','S','o','u','n','d',':',' ',0}; + static const WCHAR dsguidW[] = {'D','S','G','u','i','d',0}; + IPropertyBag *prop_bag = NULL; + REGFILTERPINS2 rgpins = {0}; + REGPINTYPES rgtypes = {0}; + REGFILTER2 rgf = {0}; + WCHAR clsid[CHARS_IN_GUID]; + IMoniker *mon = NULL; + VARIANT var; + HRESULT hr; - res = CLSIDFromString(wszFilterSubkeyName, &clsidFilter); - if (FAILED(res)) goto cleanup; + hr = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory); + if (FAILED(hr)) goto cleanup; - IFilterMapper2_RegisterFilter(pMapper, &clsidFilter, wszFilterName, &pMoniker, NULL, NULL, &rgf2); + V_VT(&var) = VT_BSTR; + if (guid) + { + WCHAR *name = heap_alloc(sizeof(defaultW) + strlenW(desc) * sizeof(WCHAR)); + if (!name) + goto cleanup; + strcpyW(name, directsoundW); + strcatW(name, desc); + + V_BSTR(&var) = SysAllocString(name); + heap_free(name); + } + else + V_BSTR(&var) = SysAllocString(defaultW); + + if (!V_BSTR(&var)) + goto cleanup; + + hr = register_codec(&CLSID_AudioRendererCategory, V_BSTR(&var), &mon); + if (FAILED(hr)) goto cleanup; + + hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); + if (FAILED(hr)) goto cleanup; + + /* write friendly name */ + hr = IPropertyBag_Write(prop_bag, wszFriendlyName, &var); + if (FAILED(hr)) goto cleanup; + VariantClear(&var); + + /* write clsid */ + V_VT(&var) = VT_BSTR; + StringFromGUID2(&CLSID_DSoundRender, clsid, CHARS_IN_GUID); + if (!(V_BSTR(&var) = SysAllocString(clsid))) + goto cleanup; + hr = IPropertyBag_Write(prop_bag, clsid_keyname, &var); + if (FAILED(hr)) goto cleanup; + VariantClear(&var); + + /* write filter data */ + rgf.dwVersion = 2; + rgf.dwMerit = guid ? MERIT_DO_NOT_USE : MERIT_PREFERRED; + rgf.u.s2.cPins2 = 1; + rgf.u.s2.rgPins2 = &rgpins; + rgpins.dwFlags = REG_PINFLAG_B_RENDERER; + /* FIXME: native registers many more formats */ + rgpins.nMediaTypes = 1; + rgpins.lpMediaType = &rgtypes; + rgtypes.clsMajorType = &MEDIATYPE_Audio; + rgtypes.clsMinorType = &MEDIASUBTYPE_PCM; + + write_filter_data(prop_bag, &rgf); + + /* write DSound guid */ + V_VT(&var) = VT_BSTR; + StringFromGUID2(guid ? guid : &GUID_NULL, clsid, CHARS_IN_GUID); + if (!(V_BSTR(&var) = SysAllocString(clsid))) + goto cleanup; + hr = IPropertyBag_Write(prop_bag, dsguidW, &var); + if (FAILED(hr)) goto cleanup; + +cleanup: + VariantClear(&var); + if (prop_bag) IPropertyBag_Release(prop_bag); + if (mon) IMoniker_Release(mon); - if (pMoniker) - IMoniker_Release(pMoniker); + return TRUE; +} - cleanup: +static void register_waveout_devices(void) +{ + static const WCHAR defaultW[] = {'D','e','f','a','u','l','t',' ','W','a','v','e','O','u','t',' ','D','e','v','i','c','e',0}; + static const WCHAR waveoutidW[] = {'W','a','v','e','O','u','t','I','d',0}; + IPropertyBag *prop_bag = NULL; + REGFILTERPINS2 rgpins = {0}; + REGPINTYPES rgtypes = {0}; + REGFILTER2 rgf = {0}; + WCHAR clsid[CHARS_IN_GUID]; + IMoniker *mon = NULL; + WAVEOUTCAPSW caps; + int i, count; + VARIANT var; + HRESULT hr; - if (hkeyFilterClass) RegCloseKey(hkeyFilterClass); + hr = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory); + if (FAILED(hr)) return; - if (rgf2.u.s1.rgPins) - { - UINT iPin; + count = waveOutGetNumDevs(); - for (iPin = 0; iPin < rgf2.u.s1.cPins; iPin++) - { - CoTaskMemFree(rgf2.u.s1.rgPins[iPin].strName); + for (i = -1; i < count; i++) + { + waveOutGetDevCapsW(i, &caps, sizeof(caps)); + + V_VT(&var) = VT_BSTR; + + if (i == -1) /* WAVE_MAPPER */ + V_BSTR(&var) = SysAllocString(defaultW); + else + V_BSTR(&var) = SysAllocString(caps.szPname); + if (!(V_BSTR(&var))) + goto cleanup; + + hr = register_codec(&CLSID_AudioRendererCategory, V_BSTR(&var), &mon); + if (FAILED(hr)) goto cleanup; + + hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); + if (FAILED(hr)) goto cleanup; + + /* write friendly name */ + hr = IPropertyBag_Write(prop_bag, wszFriendlyName, &var); + if (FAILED(hr)) goto cleanup; + VariantClear(&var); + + /* write clsid */ + V_VT(&var) = VT_BSTR; + StringFromGUID2(&CLSID_AudioRender, clsid, CHARS_IN_GUID); + if (!(V_BSTR(&var) = SysAllocString(clsid))) + goto cleanup; + hr = IPropertyBag_Write(prop_bag, clsid_keyname, &var); + if (FAILED(hr)) goto cleanup; + VariantClear(&var); + + /* write filter data */ + rgf.dwVersion = 2; + rgf.dwMerit = MERIT_DO_NOT_USE; + rgf.u.s2.cPins2 = 1; + rgf.u.s2.rgPins2 = &rgpins; + rgpins.dwFlags = REG_PINFLAG_B_RENDERER; + rgpins.nMediaTypes = 1; + rgpins.lpMediaType = &rgtypes; + rgtypes.clsMajorType = &MEDIATYPE_Audio; + rgtypes.clsMinorType = &MEDIASUBTYPE_NULL; + + write_filter_data(prop_bag, &rgf); + + /* write WaveOutId */ + V_VT(&var) = VT_I4; + V_I4(&var) = i; + hr = IPropertyBag_Write(prop_bag, waveoutidW, &var); + if (FAILED(hr)) goto cleanup; + +cleanup: + VariantClear(&var); + if (prop_bag) IPropertyBag_Release(prop_bag); + if (mon) IMoniker_Release(mon); + } +} - if (rgf2.u.s1.rgPins[iPin].lpMediaType) - { - UINT iType; +static void register_wavein_devices(void) +{ + static const WCHAR waveinidW[] = {'W','a','v','e','I','n','I','d',0}; + IPropertyBag *prop_bag = NULL; + REGFILTER2 rgf = {0}; + WCHAR clsid[CHARS_IN_GUID]; + IMoniker *mon = NULL; + WAVEINCAPSW caps; + int i, count; + VARIANT var; + HRESULT hr; - for (iType = 0; iType < rgf2.u.s1.rgPins[iPin].nMediaTypes; iType++) - { - CoTaskMemFree((void*)rgf2.u.s1.rgPins[iPin].lpMediaType[iType].clsMajorType); - CoTaskMemFree((void*)rgf2.u.s1.rgPins[iPin].lpMediaType[iType].clsMinorType); - } + hr = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory); + if (FAILED(hr)) return; - CoTaskMemFree((void*)rgf2.u.s1.rgPins[iPin].lpMediaType); - } - } + count = waveInGetNumDevs(); - CoTaskMemFree((void*)rgf2.u.s1.rgPins); - } - } - } + for (i = 0; i < count; i++) + { + waveInGetDevCapsW(i, &caps, sizeof(caps)); + + V_VT(&var) = VT_BSTR; + + V_BSTR(&var) = SysAllocString(caps.szPname); + if (!(V_BSTR(&var))) + goto cleanup; + + hr = register_codec(&CLSID_AudioInputDeviceCategory, V_BSTR(&var), &mon); + if (FAILED(hr)) goto cleanup; + + hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); + if (FAILED(hr)) goto cleanup; + + /* write friendly name */ + hr = IPropertyBag_Write(prop_bag, wszFriendlyName, &var); + if (FAILED(hr)) goto cleanup; + VariantClear(&var); + + /* write clsid */ + V_VT(&var) = VT_BSTR; + StringFromGUID2(&CLSID_AudioRecord, clsid, CHARS_IN_GUID); + if (!(V_BSTR(&var) = SysAllocString(clsid))) + goto cleanup; + hr = IPropertyBag_Write(prop_bag, clsid_keyname, &var); + if (FAILED(hr)) goto cleanup; + VariantClear(&var); + + /* write filter data */ + rgf.dwVersion = 2; + rgf.dwMerit = MERIT_DO_NOT_USE; + + write_filter_data(prop_bag, &rgf); + + /* write WaveInId */ + V_VT(&var) = VT_I4; + V_I4(&var) = i; + hr = IPropertyBag_Write(prop_bag, waveinidW, &var); + if (FAILED(hr)) goto cleanup; + +cleanup: + VariantClear(&var); + if (prop_bag) IPropertyBag_Release(prop_bag); + if (mon) IMoniker_Release(mon); } +} - if (hkeyFilter) RegCloseKey(hkeyFilter); +static void register_midiout_devices(void) +{ + static const WCHAR defaultW[] = {'D','e','f','a','u','l','t',' ','M','i','d','i','O','u','t',' ','D','e','v','i','c','e',0}; + static const WCHAR midioutidW[] = {'M','i','d','i','O','u','t','I','d',0}; + IPropertyBag *prop_bag = NULL; + REGFILTERPINS2 rgpins = {0}; + REGPINTYPES rgtypes = {0}; + REGFILTER2 rgf = {0}; + WCHAR clsid[CHARS_IN_GUID]; + IMoniker *mon = NULL; + MIDIOUTCAPSW caps; + int i, count; + VARIANT var; + HRESULT hr; - if (pMapper) - IFilterMapper2_Release(pMapper); + hr = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory); + if (FAILED(hr)) return; + + count = midiOutGetNumDevs(); - return S_OK; + for (i = -1; i < count; i++) + { + midiOutGetDevCapsW(i, &caps, sizeof(caps)); + + V_VT(&var) = VT_BSTR; + + if (i == -1) /* MIDI_MAPPER */ + V_BSTR(&var) = SysAllocString(defaultW); + else + V_BSTR(&var) = SysAllocString(caps.szPname); + if (!(V_BSTR(&var))) + goto cleanup; + + hr = register_codec(&CLSID_MidiRendererCategory, V_BSTR(&var), &mon); + if (FAILED(hr)) goto cleanup; + + hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); + if (FAILED(hr)) goto cleanup; + + /* write friendly name */ + hr = IPropertyBag_Write(prop_bag, wszFriendlyName, &var); + if (FAILED(hr)) goto cleanup; + VariantClear(&var); + + /* write clsid */ + V_VT(&var) = VT_BSTR; + StringFromGUID2(&CLSID_AVIMIDIRender, clsid, CHARS_IN_GUID); + if (!(V_BSTR(&var) = SysAllocString(clsid))) + goto cleanup; + hr = IPropertyBag_Write(prop_bag, clsid_keyname, &var); + if (FAILED(hr)) goto cleanup; + VariantClear(&var); + + /* write filter data */ + rgf.dwVersion = 2; + rgf.dwMerit = (i == -1) ? MERIT_PREFERRED : MERIT_DO_NOT_USE; + rgf.u.s2.cPins2 = 1; + rgf.u.s2.rgPins2 = &rgpins; + rgpins.dwFlags = REG_PINFLAG_B_RENDERER; + rgpins.nMediaTypes = 1; + rgpins.lpMediaType = &rgtypes; + rgtypes.clsMajorType = &MEDIATYPE_Midi; + rgtypes.clsMinorType = &MEDIASUBTYPE_NULL; + + write_filter_data(prop_bag, &rgf); + + /* write MidiOutId */ + V_VT(&var) = VT_I4; + V_I4(&var) = i; + hr = IPropertyBag_Write(prop_bag, midioutidW, &var); + if (FAILED(hr)) goto cleanup; + +cleanup: + VariantClear(&var); + if (prop_bag) IPropertyBag_Release(prop_bag); + if (mon) IMoniker_Release(mon); + } +} + +static void register_vfw_codecs(void) +{ + static const WCHAR fcchandlerW[] = {'F','c','c','H','a','n','d','l','e','r',0}; + REGFILTERPINS2 rgpins[2]; + IPropertyBag *prop_bag = NULL; + REGPINTYPES rgtypes[2]; + REGFILTER2 rgf; + WCHAR clsid[CHARS_IN_GUID]; + IMoniker *mon = NULL; + GUID typeguid; + ICINFO info; + VARIANT var; + HRESULT hr; + int i = 0; + HIC hic; + + hr = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory); + if (FAILED(hr)) return; + + while (ICInfo(ICTYPE_VIDEO, i++, &info)) + { + WCHAR name[5] = {LOBYTE(LOWORD(info.fccHandler)), HIBYTE(LOWORD(info.fccHandler)), + LOBYTE(HIWORD(info.fccHandler)), HIBYTE(HIWORD(info.fccHandler))}; + + hic = ICOpen(ICTYPE_VIDEO, info.fccHandler, ICMODE_QUERY); + ICGetInfo(hic, &info, sizeof(info)); + ICClose(hic); + + V_VT(&var) = VT_BSTR; + + V_BSTR(&var) = SysAllocString(name); + if (!(V_BSTR(&var))) + goto cleanup; + + hr = register_codec(&CLSID_VideoCompressorCategory, V_BSTR(&var), &mon); + if (FAILED(hr)) goto cleanup; + + hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); + if (FAILED(hr)) goto cleanup; + + /* write WaveInId */ + hr = IPropertyBag_Write(prop_bag, fcchandlerW, &var); + if (FAILED(hr)) goto cleanup; + VariantClear(&var); + + /* write friendly name */ + V_VT(&var) = VT_BSTR; + if (!(V_BSTR(&var) = SysAllocString(info.szDescription))) + goto cleanup; + + hr = IPropertyBag_Write(prop_bag, wszFriendlyName, &var); + if (FAILED(hr)) goto cleanup; + VariantClear(&var); + + /* write clsid */ + V_VT(&var) = VT_BSTR; + StringFromGUID2(&CLSID_AVICo, clsid, CHARS_IN_GUID); + if (!(V_BSTR(&var) = SysAllocString(clsid))) + goto cleanup; + hr = IPropertyBag_Write(prop_bag, clsid_keyname, &var); + if (FAILED(hr)) goto cleanup; + VariantClear(&var); + + /* write filter data */ + rgf.dwVersion = 2; + rgf.dwMerit = MERIT_DO_NOT_USE; + rgf.u.s2.cPins2 = 2; + rgf.u.s2.rgPins2 = rgpins; + rgpins[0].dwFlags = 0; + rgpins[0].nMediaTypes = 1; + rgpins[0].lpMediaType = &rgtypes[0]; + rgtypes[0].clsMajorType = &MEDIATYPE_Video; + typeguid = MEDIASUBTYPE_PCM; + typeguid.Data1 = info.fccHandler; + rgtypes[0].clsMinorType = &typeguid; + rgpins[1].dwFlags = REG_PINFLAG_B_OUTPUT; + rgpins[1].nMediaTypes = 1; + rgpins[1].lpMediaType = &rgtypes[1]; + rgtypes[1].clsMajorType = &MEDIATYPE_Video; + rgtypes[1].clsMinorType = &GUID_NULL; + + write_filter_data(prop_bag, &rgf); + +cleanup: + VariantClear(&var); + if (prop_bag) IPropertyBag_Release(prop_bag); + if (mon) IMoniker_Release(mon); + } } /********************************************************************** @@ -513,7 +894,6 @@ static HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator( IEnumMoniker **ppEnumMoniker, DWORD dwFlags) { - HKEY hkey, special_hkey = NULL; HRESULT hr; TRACE("(%p)->(%s, %p, %x)\n", iface, debugstr_guid(clsidDeviceClass), ppEnumMoniker, dwFlags); @@ -523,34 +903,16 @@ static HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator( *ppEnumMoniker = NULL; - if (IsEqualGUID(clsidDeviceClass, &CLSID_LegacyAmFilterCategory)) - { - DEVENUM_RegisterLegacyAmFilters(); - } - - if (IsSpecialCategory(clsidDeviceClass)) - { - hr = DEVENUM_CreateSpecialCategories(); - if (FAILED(hr)) - return hr; - - special_hkey = open_special_category_key(clsidDeviceClass, FALSE); - if (!special_hkey) - { - ERR("Couldn't open registry key for special device: %s\n", - debugstr_guid(clsidDeviceClass)); - return S_FALSE; - } - } - - hkey = open_category_key(clsidDeviceClass); - if (!hkey && !special_hkey) - { - FIXME("Category %s not found\n", debugstr_guid(clsidDeviceClass)); - return S_FALSE; - } + register_codecs(); + register_legacy_filters(); + hr = DirectSoundEnumerateW(®ister_dsound_devices, NULL); + if (FAILED(hr)) return hr; + register_waveout_devices(); + register_wavein_devices(); + register_midiout_devices(); + register_vfw_codecs(); - return DEVENUM_IEnumMoniker_Construct(hkey, special_hkey, ppEnumMoniker); + return create_EnumMoniker(clsidDeviceClass, ppEnumMoniker); } /********************************************************************** @@ -601,164 +963,33 @@ static HRESULT DEVENUM_CreateAMCategoryKey(const CLSID * clsidCategory) return res; } -static void register_vfw_codecs(void) -{ - WCHAR avico_clsid_str[CHARS_IN_GUID]; - HKEY basekey, key; - ICINFO icinfo; - DWORD i, res; - - static const WCHAR CLSIDW[] = {'C','L','S','I','D',0}; - static const WCHAR FccHandlerW[] = {'F','c','c','H','a','n','d','l','e','r',0}; - static const WCHAR FriendlyNameW[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0}; - - StringFromGUID2(&CLSID_AVICo, avico_clsid_str, sizeof(avico_clsid_str)/sizeof(WCHAR)); - - basekey = open_special_category_key(&CLSID_VideoCompressorCategory, TRUE); - if(!basekey) { - ERR("Could not create key\n"); - return; - } - - for(i=0; ICInfo(FCC('v','i','d','c'), i, &icinfo); i++) { - WCHAR fcc_str[5] = {LOBYTE(LOWORD(icinfo.fccHandler)), HIBYTE(LOWORD(icinfo.fccHandler)), - LOBYTE(HIWORD(icinfo.fccHandler)), HIBYTE(HIWORD(icinfo.fccHandler))}; - - res = RegCreateKeyW(basekey, fcc_str, &key); - if(res != ERROR_SUCCESS) - continue; - - RegSetValueExW(key, CLSIDW, 0, REG_SZ, (const BYTE*)avico_clsid_str, sizeof(avico_clsid_str)); - RegSetValueExW(key, FccHandlerW, 0, REG_SZ, (const BYTE*)fcc_str, sizeof(fcc_str)); - RegSetValueExW(key, FriendlyNameW, 0, REG_SZ, (const BYTE*)icinfo.szName, (strlenW(icinfo.szName)+1)*sizeof(WCHAR)); - /* FIXME: Set ClassManagerFlags and FilterData values */ - - RegCloseKey(key); - } - - RegCloseKey(basekey); -} - -static BOOL WINAPI acm_driver_callback(HACMDRIVERID hadid, DWORD_PTR user, DWORD support) -{ - static const WCHAR CLSIDW[] = {'C','L','S','I','D',0}; - static const WCHAR AcmIdW[] = {'A','c','m','I','d',0}; - static const WCHAR FriendlyNameW[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0}; - static const WCHAR fmtW[] = {'%','u','%','s',0}; - - WCHAR acmwrapper_clsid_str[CHARS_IN_GUID], buffer[MAX_PATH]; - HKEY key, basekey = (HKEY) user; - ACMFORMATTAGDETAILSW format; - ACMDRIVERDETAILSW driver; - HACMDRIVER had; - DWORD i, res; - - StringFromGUID2(&CLSID_ACMWrapper, acmwrapper_clsid_str, sizeof(acmwrapper_clsid_str)/sizeof(WCHAR)); - - driver.cbStruct = sizeof(driver); - if (acmDriverDetailsW(hadid, &driver, 0) != MMSYSERR_NOERROR) - return TRUE; - - if (acmDriverOpen(&had, hadid, 0) != MMSYSERR_NOERROR) - return TRUE; - - for (i = 0; i < driver.cFormatTags; i++) - { - memset(&format, 0, sizeof(format)); - format.cbStruct = sizeof(format); - format.dwFormatTagIndex = i; - - if (acmFormatTagDetailsW(had, &format, ACM_FORMATTAGDETAILSF_INDEX) != MMSYSERR_NOERROR) - continue; - - snprintfW(buffer, sizeof(buffer)/sizeof(WCHAR), fmtW, format.dwFormatTag, format.szFormatTag); - - res = RegCreateKeyW(basekey, buffer, &key); - if (res != ERROR_SUCCESS) continue; - - RegSetValueExW(key, CLSIDW, 0, REG_SZ, (BYTE*)acmwrapper_clsid_str, sizeof(acmwrapper_clsid_str)); - RegSetValueExW(key, AcmIdW, 0, REG_DWORD, (BYTE*)&format.dwFormatTag, sizeof(DWORD)); - RegSetValueExW(key, FriendlyNameW, 0, REG_SZ, (BYTE*)format.szFormatTag, (strlenW(format.szFormatTag)+1)*sizeof(WCHAR)); - /* FIXME: Set FilterData values */ - - RegCloseKey(key); - } - - acmDriverClose(had, 0); - - return TRUE; -} - -static void register_acm_codecs(void) -{ - HKEY basekey; - - basekey = open_special_category_key(&CLSID_AudioCompressorCategory, TRUE); - if (!basekey) - { - ERR("Could not create key\n"); - return; - } - - acmDriverEnum(acm_driver_callback, (DWORD_PTR)basekey, 0); - - RegCloseKey(basekey); -} - -static HANDLE DEVENUM_populate_handle; -static const WCHAR DEVENUM_populate_handle_nameW[] = - {'_','_','W','I','N','E','_', - 'D','e','v','e','n','u','m','_', - 'P','o','p','u','l','a','t','e',0}; - -/********************************************************************** - * DEVENUM_CreateSpecialCategories (INTERNAL) - * - * Creates the keys in the registry for the dynamic categories - */ -static HRESULT DEVENUM_CreateSpecialCategories(void) +static HRESULT register_codecs(void) { HRESULT res; - WCHAR szDSoundNameFormat[MAX_PATH + 1]; - WCHAR szDSoundName[MAX_PATH + 1]; + WCHAR class[CHARS_IN_GUID]; DWORD iDefaultDevice = -1; - UINT numDevs; IFilterMapper2 * pMapper = NULL; REGFILTER2 rf2; REGFILTERPINS2 rfp2; - WCHAR path[MAX_PATH]; HKEY basekey; - if (DEVENUM_populate_handle) - return S_OK; - DEVENUM_populate_handle = CreateEventW(NULL, TRUE, FALSE, DEVENUM_populate_handle_nameW); - if (GetLastError() == ERROR_ALREADY_EXISTS) - { - /* Webcams can take some time to scan if the driver is badly written and it enables them, - * so have a 10 s timeout here - */ - if (WaitForSingleObject(DEVENUM_populate_handle, 10000) == WAIT_TIMEOUT) - WARN("Waiting for object timed out\n"); - TRACE("No need to rescan\n"); - return S_OK; - } - TRACE("Scanning for devices\n"); - /* Since devices can change between session, for example because you just plugged in a webcam * or switched from pulseaudio to alsa, delete all old devices first */ - if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_AudioRendererCategory, &basekey, path, MAX_PATH))) - RegDeleteTreeW(basekey, path); - if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_AudioInputDeviceCategory, &basekey, path, MAX_PATH))) - RegDeleteTreeW(basekey, path); - if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_VideoInputDeviceCategory, &basekey, path, MAX_PATH))) - RegDeleteTreeW(basekey, path); - if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_MidiRendererCategory, &basekey, path, MAX_PATH))) - RegDeleteTreeW(basekey, path); - if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_VideoCompressorCategory, &basekey, path, MAX_PATH))) - RegDeleteTreeW(basekey, path); - if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_AudioCompressorCategory, &basekey, path, MAX_PATH))) - RegDeleteTreeW(basekey, path); + RegOpenKeyW(HKEY_CURRENT_USER, wszActiveMovieKey, &basekey); + StringFromGUID2(&CLSID_LegacyAmFilterCategory, class, CHARS_IN_GUID); + RegDeleteTreeW(basekey, class); + StringFromGUID2(&CLSID_AudioRendererCategory, class, CHARS_IN_GUID); + RegDeleteTreeW(basekey, class); + StringFromGUID2(&CLSID_AudioInputDeviceCategory, class, CHARS_IN_GUID); + RegDeleteTreeW(basekey, class); + StringFromGUID2(&CLSID_VideoInputDeviceCategory, class, CHARS_IN_GUID); + RegDeleteTreeW(basekey, class); + StringFromGUID2(&CLSID_MidiRendererCategory, class, CHARS_IN_GUID); + RegDeleteTreeW(basekey, class); + StringFromGUID2(&CLSID_VideoCompressorCategory, class, CHARS_IN_GUID); + RegDeleteTreeW(basekey, class); + RegCloseKey(basekey); rf2.dwVersion = 2; rf2.dwMerit = MERIT_PREFERRED; @@ -769,12 +1000,6 @@ static HRESULT DEVENUM_CreateSpecialCategories(void) rfp2.lpMedium = NULL; rfp2.clsPinCategory = &IID_NULL; - if (!LoadStringW(DEVENUM_hInstance, IDS_DEVENUM_DS, szDSoundNameFormat, sizeof(szDSoundNameFormat)/sizeof(szDSoundNameFormat[0])-1)) - { - ERR("Couldn't get string resource (GetLastError() is %d)\n", GetLastError()); - return HRESULT_FROM_WIN32(GetLastError()); - } - res = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC, &IID_IFilterMapper2, (void **) &pMapper); /* @@ -783,205 +1008,9 @@ static HRESULT DEVENUM_CreateSpecialCategories(void) if (SUCCEEDED(res)) { UINT i; - WAVEOUTCAPSW wocaps; - WAVEINCAPSW wicaps; - MIDIOUTCAPSW mocaps; REGPINTYPES * pTypes; IPropertyBag * pPropBag = NULL; - numDevs = waveOutGetNumDevs(); - - res = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory); - if (FAILED(res)) /* can't register any devices in this category */ - numDevs = 0; - - rfp2.dwFlags = REG_PINFLAG_B_RENDERER; - for (i = 0; i < numDevs; i++) - { - if (waveOutGetDevCapsW(i, &wocaps, sizeof(WAVEOUTCAPSW)) - == MMSYSERR_NOERROR) - { - IMoniker * pMoniker = NULL; - - rfp2.nMediaTypes = 1; - pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES)); - if (!pTypes) - { - IFilterMapper2_Release(pMapper); - return E_OUTOFMEMORY; - } - /* FIXME: Native devenum seems to register a lot more types for - * DSound than we do. Not sure what purpose they serve */ - pTypes[0].clsMajorType = &MEDIATYPE_Audio; - pTypes[0].clsMinorType = &MEDIASUBTYPE_PCM; - - rfp2.lpMediaType = pTypes; - - res = IFilterMapper2_RegisterFilter(pMapper, - &CLSID_AudioRender, - wocaps.szPname, - &pMoniker, - &CLSID_AudioRendererCategory, - wocaps.szPname, - &rf2); - - if (pMoniker) - { - VARIANT var; - - V_VT(&var) = VT_I4; - V_I4(&var) = i; - res = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID)&pPropBag); - if (SUCCEEDED(res)) - res = IPropertyBag_Write(pPropBag, wszWaveOutID, &var); - else - pPropBag = NULL; - - V_VT(&var) = VT_LPWSTR; - V_BSTR(&var) = wocaps.szPname; - if (SUCCEEDED(res)) - res = IPropertyBag_Write(pPropBag, wszFriendlyName, &var); - if (pPropBag) - IPropertyBag_Release(pPropBag); - IMoniker_Release(pMoniker); - pMoniker = NULL; - } - - wsprintfW(szDSoundName, szDSoundNameFormat, wocaps.szPname); - res = IFilterMapper2_RegisterFilter(pMapper, - &CLSID_DSoundRender, - szDSoundName, - &pMoniker, - &CLSID_AudioRendererCategory, - szDSoundName, - &rf2); - - /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */ - - if (pMoniker) - IMoniker_Release(pMoniker); - - if (i == iDefaultDevice) - { - FIXME("Default device\n"); - } - - CoTaskMemFree(pTypes); - } - } - - numDevs = waveInGetNumDevs(); - - res = DEVENUM_CreateAMCategoryKey(&CLSID_AudioInputDeviceCategory); - if (FAILED(res)) /* can't register any devices in this category */ - numDevs = 0; - - rfp2.dwFlags = REG_PINFLAG_B_OUTPUT; - for (i = 0; i < numDevs; i++) - { - if (waveInGetDevCapsW(i, &wicaps, sizeof(WAVEINCAPSW)) - == MMSYSERR_NOERROR) - { - IMoniker * pMoniker = NULL; - - rfp2.nMediaTypes = 1; - pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES)); - if (!pTypes) - { - IFilterMapper2_Release(pMapper); - return E_OUTOFMEMORY; - } - - /* FIXME: Not sure if these are correct */ - pTypes[0].clsMajorType = &MEDIATYPE_Audio; - pTypes[0].clsMinorType = &MEDIASUBTYPE_PCM; - - rfp2.lpMediaType = pTypes; - - res = IFilterMapper2_RegisterFilter(pMapper, - &CLSID_AudioRecord, - wicaps.szPname, - &pMoniker, - &CLSID_AudioInputDeviceCategory, - wicaps.szPname, - &rf2); - - - if (pMoniker) { - VARIANT var; - - V_VT(&var) = VT_I4; - V_I4(&var) = i; - res = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID)&pPropBag); - if (SUCCEEDED(res)) - res = IPropertyBag_Write(pPropBag, wszWaveInID, &var); - else - pPropBag = NULL; - - V_VT(&var) = VT_LPWSTR; - V_BSTR(&var) = wicaps.szPname; - if (SUCCEEDED(res)) - res = IPropertyBag_Write(pPropBag, wszFriendlyName, &var); - - if (pPropBag) - IPropertyBag_Release(pPropBag); - IMoniker_Release(pMoniker); - } - - CoTaskMemFree(pTypes); - } - } - - numDevs = midiOutGetNumDevs(); - - res = DEVENUM_CreateAMCategoryKey(&CLSID_MidiRendererCategory); - if (FAILED(res)) /* can't register any devices in this category */ - numDevs = 0; - - rfp2.dwFlags = REG_PINFLAG_B_RENDERER; - for (i = 0; i < numDevs; i++) - { - if (midiOutGetDevCapsW(i, &mocaps, sizeof(MIDIOUTCAPSW)) - == MMSYSERR_NOERROR) - { - IMoniker * pMoniker = NULL; - - rfp2.nMediaTypes = 1; - pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES)); - if (!pTypes) - { - IFilterMapper2_Release(pMapper); - return E_OUTOFMEMORY; - } - - /* FIXME: Not sure if these are correct */ - pTypes[0].clsMajorType = &MEDIATYPE_Midi; - pTypes[0].clsMinorType = &MEDIASUBTYPE_None; - - rfp2.lpMediaType = pTypes; - - res = IFilterMapper2_RegisterFilter(pMapper, - &CLSID_AVIMIDIRender, - mocaps.szPname, - &pMoniker, - &CLSID_MidiRendererCategory, - mocaps.szPname, - &rf2); - - /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */ - /* Native version sets MidiOutId */ - - if (pMoniker) - IMoniker_Release(pMoniker); - - if (i == iDefaultDevice) - { - FIXME("Default device\n"); - } - - CoTaskMemFree(pTypes); - } - } res = DEVENUM_CreateAMCategoryKey(&CLSID_VideoInputDeviceCategory); if (SUCCEEDED(res)) for (i = 0; i < 10; i++) @@ -1039,9 +1068,5 @@ static HRESULT DEVENUM_CreateSpecialCategories(void) if (pMapper) IFilterMapper2_Release(pMapper); - register_vfw_codecs(); - register_acm_codecs(); - - SetEvent(DEVENUM_populate_handle); return res; } diff --git a/dll/directx/wine/devenum/devenum.rc b/dll/directx/wine/devenum/devenum.rc index 294d41ff23..1cc74a4394 100644 --- a/dll/directx/wine/devenum/devenum.rc +++ b/dll/directx/wine/devenum/devenum.rc @@ -23,18 +23,6 @@ #include "winnls.h" #include "devenum_private.h" -#pragma makedep po - -LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT - -STRINGTABLE -{ - IDS_DEVENUM_DSDEFAULT "Default DirectSound" - IDS_DEVENUM_DS "DirectSound: %s" - IDS_DEVENUM_WODEFAULT "Default WaveOut Device" - IDS_DEVENUM_MIDEFAULT "Default MidiOut Device" -} - LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL #define WINE_FILEDESCRIPTION_STR "Wine Device Enumerator Library" diff --git a/dll/directx/wine/devenum/devenum_private.h b/dll/directx/wine/devenum/devenum_private.h index 72c285d422..005f0b56e6 100644 --- a/dll/directx/wine/devenum/devenum_private.h +++ b/dll/directx/wine/devenum/devenum_private.h @@ -62,38 +62,40 @@ typedef struct IClassFactory IClassFactory_iface; } ClassFactoryImpl; +enum device_type +{ + DEVICE_FILTER, + DEVICE_CODEC, +}; + typedef struct { IMoniker IMoniker_iface; LONG ref; - HKEY hkey; + CLSID class; + BOOL has_class; + enum device_type type; + WCHAR *name; } MediaCatMoniker; MediaCatMoniker * DEVENUM_IMediaCatMoniker_Construct(void) DECLSPEC_HIDDEN; -HRESULT DEVENUM_IEnumMoniker_Construct(HKEY hkey, HKEY special_hkey, IEnumMoniker ** ppEnumMoniker) DECLSPEC_HIDDEN; +HRESULT create_EnumMoniker(REFCLSID class, IEnumMoniker **enum_mon) DECLSPEC_HIDDEN; extern ClassFactoryImpl DEVENUM_ClassFactory DECLSPEC_HIDDEN; extern ICreateDevEnum DEVENUM_CreateDevEnum DECLSPEC_HIDDEN; extern IParseDisplayName DEVENUM_ParseDisplayName DECLSPEC_HIDDEN; -/********************************************************************** - * Private helper function to get AM filter category key location - */ -HRESULT DEVENUM_GetCategoryKey(REFCLSID clsidDeviceClass, HKEY *pBaseKey, WCHAR *wszRegKeyName, UINT maxLen) DECLSPEC_HIDDEN; - /********************************************************************** * Global string constant declarations */ -extern const WCHAR clsid_keyname[6] DECLSPEC_HIDDEN; -extern const WCHAR wszInstanceKeyName[] DECLSPEC_HIDDEN; -#define CLSID_STR_LEN (sizeof(clsid_keyname) / sizeof(WCHAR)) -/********************************************************************** - * Resource IDs - */ -#define IDS_DEVENUM_DSDEFAULT 7 -#define IDS_DEVENUM_DS 8 -#define IDS_DEVENUM_WODEFAULT 9 -#define IDS_DEVENUM_MIDEFAULT 10 -#define IDS_DEVENUM_KSDEFAULT 11 -#define IDS_DEVENUM_KS 12 +static const WCHAR backslashW[] = {'\\',0}; +static const WCHAR clsidW[] = {'C','L','S','I','D','\\',0}; +static const WCHAR instanceW[] = {'\\','I','n','s','t','a','n','c','e',0}; +static const WCHAR wszActiveMovieKey[] = {'S','o','f','t','w','a','r','e','\\', + 'M','i','c','r','o','s','o','f','t','\\', + 'A','c','t','i','v','e','M','o','v','i','e','\\', + 'd','e','v','e','n','u','m','\\',0}; +static const WCHAR deviceW[] = {'@','d','e','v','i','c','e',':',0}; + +extern const WCHAR clsid_keyname[6] DECLSPEC_HIDDEN; diff --git a/dll/directx/wine/devenum/fil_data.idl b/dll/directx/wine/devenum/fil_data.idl new file mode 100644 index 0000000000..7e37a755d9 --- /dev/null +++ b/dll/directx/wine/devenum/fil_data.idl @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2009 Vitaliy Margolen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma makedep header + +import "objidl.idl"; +import "strmif.idl"; +import "unknwn.idl"; + + +/***************************************************************************** + * IAMFilterData interface + */ +[ + object, + uuid(97f7c4d4-547b-4a5f-8332-536430ad2e4d), + pointer_default(unique) +] +interface IAMFilterData : IUnknown +{ + typedef [unique] IAMFilterData *LPIAMFILTERDATA; + + HRESULT ParseFilterData( + [in] BYTE * rgbFilterData, + [in] ULONG cb, + [out] BYTE ** prgbRegFilter2); + + HRESULT CreateFilterData( + [in] REGFILTER2 * prf2, + [out] BYTE ** prgbFilterData, + [out] ULONG * pcb); +} diff --git a/dll/directx/wine/devenum/mediacatenum.c b/dll/directx/wine/devenum/mediacatenum.c index 4edc4e9622..a76c7bebfb 100644 --- a/dll/directx/wine/devenum/mediacatenum.c +++ b/dll/directx/wine/devenum/mediacatenum.c @@ -33,18 +33,20 @@ WINE_DEFAULT_DEBUG_CHANNEL(devenum); typedef struct { IEnumMoniker IEnumMoniker_iface; + CLSID class; LONG ref; - DWORD index; - DWORD subkey_cnt; - HKEY hkey; - HKEY special_hkey; + HKEY sw_key; + DWORD sw_index; + HKEY cm_key; + DWORD cm_index; } EnumMonikerImpl; typedef struct { IPropertyBag IPropertyBag_iface; LONG ref; - HKEY hkey; + enum device_type type; + WCHAR path[MAX_PATH]; } RegPropBagImpl; @@ -100,7 +102,6 @@ static ULONG WINAPI DEVENUM_IPropertyBag_Release(LPPROPERTYBAG iface) ref = InterlockedDecrement(&This->ref); if (ref == 0) { - RegCloseKey(This->hkey); CoTaskMemFree(This); DEVENUM_UnlockModule(); } @@ -118,22 +119,32 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Read( DWORD type = 0; RegPropBagImpl *This = impl_from_IPropertyBag(iface); HRESULT res = S_OK; - LONG reswin32; + LONG reswin32 = ERROR_SUCCESS; + HKEY hkey; TRACE("(%p)->(%s, %p, %p)\n", This, debugstr_w(pszPropName), pVar, pErrorLog); if (!pszPropName || !pVar) return E_POINTER; - reswin32 = RegQueryValueExW(This->hkey, pszPropName, NULL, NULL, NULL, &received); + if (This->type == DEVICE_FILTER) + reswin32 = RegOpenKeyW(HKEY_CLASSES_ROOT, This->path, &hkey); + else if (This->type == DEVICE_CODEC) + reswin32 = RegOpenKeyW(HKEY_CURRENT_USER, This->path, &hkey); res = HRESULT_FROM_WIN32(reswin32); + if (SUCCEEDED(res)) + { + reswin32 = RegQueryValueExW(hkey, pszPropName, NULL, NULL, NULL, &received); + res = HRESULT_FROM_WIN32(reswin32); + } + if (SUCCEEDED(res)) { pData = HeapAlloc(GetProcessHeap(), 0, received); /* work around a GCC bug that occurs here unless we use the reswin32 variable as well */ - reswin32 = RegQueryValueExW(This->hkey, pszPropName, NULL, &type, pData, &received); + reswin32 = RegQueryValueExW(hkey, pszPropName, NULL, &type, pData, &received); res = HRESULT_FROM_WIN32(reswin32); } @@ -214,6 +225,8 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Read( HeapFree(GetProcessHeap(), 0, pData); + RegCloseKey(hkey); + TRACE("<- %x\n", res); return res; } @@ -228,6 +241,8 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Write( DWORD cbData = 0; DWORD dwType = 0; HRESULT res = S_OK; + LONG lres = ERROR_SUCCESS; + HKEY hkey; TRACE("(%p)->(%s, %p)\n", This, debugstr_w(pszPropName), pVar); @@ -264,10 +279,18 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Write( return E_FAIL; } - if (RegSetValueExW(This->hkey, - pszPropName, 0, - dwType, lpData, cbData) != ERROR_SUCCESS) - res = E_FAIL; + if (This->type == DEVICE_FILTER) + lres = RegCreateKeyW(HKEY_CLASSES_ROOT, This->path, &hkey); + else if (This->type == DEVICE_CODEC) + lres = RegCreateKeyW(HKEY_CURRENT_USER, This->path, &hkey); + res = HRESULT_FROM_WIN32(lres); + + if (SUCCEEDED(res)) + { + lres = RegSetValueExW(hkey, pszPropName, 0, dwType, lpData, cbData); + res = HRESULT_FROM_WIN32(lres); + RegCloseKey(hkey); + } if (V_VT(pVar) & VT_ARRAY) res = SafeArrayUnaccessData(V_ARRAY(pVar)); @@ -284,14 +307,28 @@ static const IPropertyBagVtbl IPropertyBag_Vtbl = DEVENUM_IPropertyBag_Write }; -static HRESULT DEVENUM_IPropertyBag_Construct(HANDLE hkey, IPropertyBag **ppBag) +static HRESULT create_PropertyBag(MediaCatMoniker *mon, IPropertyBag **ppBag) { RegPropBagImpl * rpb = CoTaskMemAlloc(sizeof(RegPropBagImpl)); if (!rpb) return E_OUTOFMEMORY; rpb->IPropertyBag_iface.lpVtbl = &IPropertyBag_Vtbl; rpb->ref = 1; - rpb->hkey = hkey; + rpb->type = mon->type; + + if (rpb->type == DEVICE_FILTER) + strcpyW(rpb->path, clsidW); + else if (rpb->type == DEVICE_CODEC) + strcpyW(rpb->path, wszActiveMovieKey); + if (mon->has_class) + { + StringFromGUID2(&mon->class, rpb->path + strlenW(rpb->path), CHARS_IN_GUID); + if (rpb->type == DEVICE_FILTER) + strcatW(rpb->path, instanceW); + strcatW(rpb->path, backslashW); + } + strcatW(rpb->path, mon->name); + *ppBag = &rpb->IPropertyBag_iface; DEVENUM_LockModule(); return S_OK; @@ -344,7 +381,7 @@ static ULONG WINAPI DEVENUM_IMediaCatMoniker_Release(IMoniker *iface) TRACE("(%p) ref=%d\n", This, ref); if (ref == 0) { - RegCloseKey(This->hkey); + CoTaskMemFree(This->name); CoTaskMemFree(This); DEVENUM_UnlockModule(); } @@ -407,6 +444,9 @@ static HRESULT WINAPI DEVENUM_IMediaCatMoniker_BindToObject(IMoniker *iface, IBi TRACE("(%p)->(%p, %p, %s, %p)\n", This, pbc, pmkToLeft, debugstr_guid(riidResult), ppvResult); + if (!ppvResult) + return E_POINTER; + VariantInit(&var); *ppvResult = NULL; @@ -485,9 +525,7 @@ static HRESULT WINAPI DEVENUM_IMediaCatMoniker_BindToStorage(IMoniker *iface, IB if (IsEqualGUID(riid, &IID_IPropertyBag)) { - HANDLE hkey; - DuplicateHandle(GetCurrentProcess(), This->hkey, GetCurrentProcess(), &hkey, 0, 0, DUPLICATE_SAME_ACCESS); - return DEVENUM_IPropertyBag_Construct(hkey, (IPropertyBag**)ppvObj); + return create_PropertyBag(This, (IPropertyBag**)ppvObj); } return MK_E_NOSTORAGE; @@ -620,24 +658,35 @@ static HRESULT WINAPI DEVENUM_IMediaCatMoniker_RelativePathTo(IMoniker *iface, I static HRESULT WINAPI DEVENUM_IMediaCatMoniker_GetDisplayName(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, LPOLESTR *ppszDisplayName) { + static const WCHAR swW[] = {'s','w',':',0}; + static const WCHAR cmW[] = {'c','m',':',0}; MediaCatMoniker *This = impl_from_IMoniker(iface); - WCHAR wszBuffer[MAX_PATH]; - static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0}; - DWORD received = sizeof(wszBuffer); + WCHAR *buffer; TRACE("(%p)->(%p, %p, %p)\n", iface, pbc, pmkToLeft, ppszDisplayName); *ppszDisplayName = NULL; - /* FIXME: should this be the weird stuff we have to parse in IParseDisplayName? */ - if (RegQueryValueExW(This->hkey, wszFriendlyName, NULL, NULL, (LPBYTE)wszBuffer, &received) == ERROR_SUCCESS) + buffer = CoTaskMemAlloc((strlenW(deviceW) + 4 + (This->has_class ? CHARS_IN_GUID : 0) + + strlenW(This->name) + 1) * sizeof(WCHAR)); + if (!buffer) + return E_OUTOFMEMORY; + + strcpyW(buffer, deviceW); + if (This->type == DEVICE_FILTER) + strcatW(buffer, swW); + else if (This->type == DEVICE_CODEC) + strcatW(buffer, cmW); + + if (This->has_class) { - *ppszDisplayName = CoTaskMemAlloc(received); - strcpyW(*ppszDisplayName, wszBuffer); - return S_OK; + StringFromGUID2(&This->class, buffer + strlenW(buffer), CHARS_IN_GUID); + strcatW(buffer, backslashW); } + strcatW(buffer, This->name); - return E_FAIL; + *ppszDisplayName = buffer; + return S_OK; } static HRESULT WINAPI DEVENUM_IMediaCatMoniker_ParseDisplayName(IMoniker *iface, IBindCtx *pbc, @@ -694,7 +743,8 @@ MediaCatMoniker * DEVENUM_IMediaCatMoniker_Construct(void) pMoniker->IMoniker_iface.lpVtbl = &IMoniker_Vtbl; pMoniker->ref = 0; - pMoniker->hkey = NULL; + pMoniker->has_class = FALSE; + pMoniker->name = NULL; DEVENUM_IMediaCatMoniker_AddRef(&pMoniker->IMoniker_iface); @@ -748,9 +798,8 @@ static ULONG WINAPI DEVENUM_IEnumMoniker_Release(IEnumMoniker *iface) if (!ref) { - if(This->special_hkey) - RegCloseKey(This->special_hkey); - RegCloseKey(This->hkey); + RegCloseKey(This->sw_key); + RegCloseKey(This->cm_key); CoTaskMemFree(This); DEVENUM_UnlockModule(); return 0; @@ -766,37 +815,55 @@ static HRESULT WINAPI DEVENUM_IEnumMoniker_Next(IEnumMoniker *iface, ULONG celt, LONG res; ULONG fetched = 0; MediaCatMoniker * pMoniker; + HKEY hkey; TRACE("(%p)->(%d, %p, %p)\n", iface, celt, rgelt, pceltFetched); while (fetched < celt) { - if(This->index+fetched < This->subkey_cnt) - res = RegEnumKeyW(This->hkey, This->index+fetched, buffer, sizeof(buffer) / sizeof(WCHAR)); - else if(This->special_hkey) - res = RegEnumKeyW(This->special_hkey, This->index+fetched-This->subkey_cnt, buffer, sizeof(buffer) / sizeof(WCHAR)); - else - break; - if (res != ERROR_SUCCESS) + /* FIXME: try PNP devices and DMOs first */ + + /* try DirectShow filters */ + if (!(res = RegEnumKeyW(This->sw_key, This->sw_index, buffer, sizeof(buffer)/sizeof(WCHAR)))) { - break; + This->sw_index++; + if ((res = RegOpenKeyExW(This->sw_key, buffer, 0, KEY_QUERY_VALUE, &hkey))) + break; + + if (!(pMoniker = DEVENUM_IMediaCatMoniker_Construct())) + return E_OUTOFMEMORY; + + pMoniker->type = DEVICE_FILTER; } - pMoniker = DEVENUM_IMediaCatMoniker_Construct(); - if (!pMoniker) - return E_OUTOFMEMORY; + /* then try codecs */ + else if (!(res = RegEnumKeyW(This->cm_key, This->cm_index, buffer, sizeof(buffer)/sizeof(WCHAR)))) + { + This->cm_index++; + + if ((res = RegOpenKeyExW(This->cm_key, buffer, 0, KEY_QUERY_VALUE, &hkey))) + break; - if (RegOpenKeyW(This->index+fetched < This->subkey_cnt ? This->hkey : This->special_hkey, - buffer, &pMoniker->hkey) != ERROR_SUCCESS) + if (!(pMoniker = DEVENUM_IMediaCatMoniker_Construct())) + return E_OUTOFMEMORY; + + pMoniker->type = DEVICE_CODEC; + } + else + break; + + if (!(pMoniker->name = CoTaskMemAlloc((strlenW(buffer) + 1) * sizeof(WCHAR)))) { IMoniker_Release(&pMoniker->IMoniker_iface); - break; + return E_OUTOFMEMORY; } + strcpyW(pMoniker->name, buffer); + pMoniker->has_class = TRUE; + pMoniker->class = This->class; + rgelt[fetched] = &pMoniker->IMoniker_iface; fetched++; } - This->index += fetched; - TRACE("-- fetched %d\n", fetched); if (pceltFetched) @@ -811,21 +878,26 @@ static HRESULT WINAPI DEVENUM_IEnumMoniker_Next(IEnumMoniker *iface, ULONG celt, static HRESULT WINAPI DEVENUM_IEnumMoniker_Skip(IEnumMoniker *iface, ULONG celt) { EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); - DWORD special_subkeys = 0; TRACE("(%p)->(%d)\n", iface, celt); - /* Before incrementing, check if there are any more values to run through. - Some programs use the Skip() function to get the number of devices */ - if(This->special_hkey) - RegQueryInfoKeyW(This->special_hkey, NULL, NULL, NULL, &special_subkeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - - if((This->index + celt) >= This->subkey_cnt + special_subkeys) + while (celt--) { - return S_FALSE; - } + /* FIXME: try PNP devices and DMOs first */ - This->index += celt; + /* try DirectShow filters */ + if (RegEnumKeyW(This->sw_key, This->sw_index, NULL, 0) != ERROR_NO_MORE_ITEMS) + { + This->sw_index++; + } + /* then try codecs */ + else if (RegEnumKeyW(This->cm_key, This->cm_index, NULL, 0) != ERROR_NO_MORE_ITEMS) + { + This->cm_index++; + } + else + return S_FALSE; + } return S_OK; } @@ -836,7 +908,8 @@ static HRESULT WINAPI DEVENUM_IEnumMoniker_Reset(IEnumMoniker *iface) TRACE("(%p)->()\n", iface); - This->index = 0; + This->sw_index = 0; + This->cm_index = 0; return S_OK; } @@ -862,23 +935,32 @@ static const IEnumMonikerVtbl IEnumMoniker_Vtbl = DEVENUM_IEnumMoniker_Clone }; -HRESULT DEVENUM_IEnumMoniker_Construct(HKEY hkey, HKEY special_hkey, IEnumMoniker ** ppEnumMoniker) +HRESULT create_EnumMoniker(REFCLSID class, IEnumMoniker **ppEnumMoniker) { EnumMonikerImpl * pEnumMoniker = CoTaskMemAlloc(sizeof(EnumMonikerImpl)); + WCHAR buffer[78]; + if (!pEnumMoniker) return E_OUTOFMEMORY; pEnumMoniker->IEnumMoniker_iface.lpVtbl = &IEnumMoniker_Vtbl; pEnumMoniker->ref = 1; - pEnumMoniker->index = 0; - pEnumMoniker->hkey = hkey; - pEnumMoniker->special_hkey = special_hkey; + pEnumMoniker->sw_index = 0; + pEnumMoniker->cm_index = 0; + pEnumMoniker->class = *class; - *ppEnumMoniker = &pEnumMoniker->IEnumMoniker_iface; + strcpyW(buffer, clsidW); + StringFromGUID2(class, buffer + strlenW(buffer), CHARS_IN_GUID); + strcatW(buffer, instanceW); + if (RegOpenKeyExW(HKEY_CLASSES_ROOT, buffer, 0, KEY_ENUMERATE_SUB_KEYS, &pEnumMoniker->sw_key)) + pEnumMoniker->sw_key = NULL; - if(RegQueryInfoKeyW(pEnumMoniker->hkey, NULL, NULL, NULL, &pEnumMoniker->subkey_cnt, NULL, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) - pEnumMoniker->subkey_cnt = 0; + strcpyW(buffer, wszActiveMovieKey); + StringFromGUID2(class, buffer + strlenW(buffer), CHARS_IN_GUID); + if (RegOpenKeyExW(HKEY_CURRENT_USER, buffer, 0, KEY_ENUMERATE_SUB_KEYS, &pEnumMoniker->cm_key)) + pEnumMoniker->cm_key = NULL; + *ppEnumMoniker = &pEnumMoniker->IEnumMoniker_iface; DEVENUM_LockModule(); diff --git a/dll/directx/wine/devenum/parsedisplayname.c b/dll/directx/wine/devenum/parsedisplayname.c index 77ea1ecdcb..0f3ef3be5a 100644 --- a/dll/directx/wine/devenum/parsedisplayname.c +++ b/dll/directx/wine/devenum/parsedisplayname.c @@ -76,69 +76,60 @@ static ULONG WINAPI DEVENUM_IParseDisplayName_Release(IParseDisplayName *iface) * not in "@device:sw:{CLSID1}\<filter name or CLSID>" format */ static HRESULT WINAPI DEVENUM_IParseDisplayName_ParseDisplayName(IParseDisplayName *iface, - IBindCtx *pbc, LPOLESTR pszDisplayName, ULONG *pchEaten, IMoniker **ppmkOut) + IBindCtx *pbc, LPOLESTR name, ULONG *eaten, IMoniker **ret) { - LPOLESTR pszBetween = NULL; - LPOLESTR pszClass = NULL; - MediaCatMoniker * pMoniker = NULL; - CLSID clsidDevice; - HRESULT res = S_OK; - WCHAR wszRegKeyName[MAX_PATH]; - HKEY hbasekey; - int classlen; - static const WCHAR wszRegSeparator[] = {'\\', 0 }; - - TRACE("(%p, %s, %p, %p)\n", pbc, debugstr_w(pszDisplayName), pchEaten, ppmkOut); - - *ppmkOut = NULL; - if (pchEaten) - *pchEaten = strlenW(pszDisplayName); - - pszDisplayName = strchrW(pszDisplayName, '{'); - pszBetween = strchrW(pszDisplayName, '}') + 2; - - /* size = pszBetween - pszDisplayName - 1 (for '\\' after CLSID) - * + 1 (for NULL character) - */ - classlen = (int)(pszBetween - pszDisplayName - 1); - pszClass = CoTaskMemAlloc((classlen + 1) * sizeof(WCHAR)); - if (!pszClass) - return E_OUTOFMEMORY; + WCHAR buffer[MAX_PATH]; + enum device_type type; + MediaCatMoniker *mon; + CLSID class; + + TRACE("(%p, %s, %p, %p)\n", pbc, debugstr_w(name), eaten, ret); + + *ret = NULL; + if (eaten) + *eaten = strlenW(name); - memcpy(pszClass, pszDisplayName, classlen * sizeof(WCHAR)); - pszClass[classlen] = 0; + name = strchrW(name, ':') + 1; - TRACE("Device CLSID: %s\n", debugstr_w(pszClass)); + if (name[0] == 's' && name[1] == 'w' && name[2] == ':') + { + type = DEVICE_FILTER; + name += 3; + } + else if (name[0] == 'c' && name[1] == 'm' && name[2] == ':') + { + type = DEVICE_CODEC; + name += 3; + } + else + { + FIXME("unhandled device type %s\n", debugstr_w(name)); + return MK_E_SYNTAX; + } - res = CLSIDFromString(pszClass, &clsidDevice); + if (!(mon = DEVENUM_IMediaCatMoniker_Construct())) + return E_OUTOFMEMORY; - if (SUCCEEDED(res)) + lstrcpynW(buffer, name, CHARS_IN_GUID); + if (CLSIDFromString(buffer, &class) == S_OK) { - res = DEVENUM_GetCategoryKey(&clsidDevice, &hbasekey, wszRegKeyName, MAX_PATH); + mon->has_class = TRUE; + mon->class = class; + name += CHARS_IN_GUID; } - if (SUCCEEDED(res)) + mon->type = type; + + if (!(mon->name = CoTaskMemAlloc((strlenW(name) + 1) * sizeof(WCHAR)))) { - pMoniker = DEVENUM_IMediaCatMoniker_Construct(); - if (pMoniker) - { - strcatW(wszRegKeyName, wszRegSeparator); - strcatW(wszRegKeyName, pszBetween); - - if (RegCreateKeyW(hbasekey, wszRegKeyName, &pMoniker->hkey) == ERROR_SUCCESS) - *ppmkOut = &pMoniker->IMoniker_iface; - else - { - IMoniker_Release(&pMoniker->IMoniker_iface); - res = MK_E_NOOBJECT; - } - } + IMoniker_Release(&mon->IMoniker_iface); + return E_OUTOFMEMORY; } + strcpyW(mon->name, name); - CoTaskMemFree(pszClass); + *ret = &mon->IMoniker_iface; - TRACE("-- returning: %x\n", res); - return res; + return S_OK; } /********************************************************************** diff --git a/media/doc/README.WINE b/media/doc/README.WINE index 477bb4d3e3..a5b6b1865a 100644 --- a/media/doc/README.WINE +++ b/media/doc/README.WINE @@ -29,7 +29,7 @@ reactos/dll/directx/wine/d3drm # Synced to WineStaging-3.9 reactos/dll/directx/wine/d3dx9_24 => 43 # Synced to WineStaging-3.9 reactos/dll/directx/wine/d3dxof # Synced to WineStaging-3.3 reactos/dll/directx/wine/ddraw # Synced to WineStaging-3.9 -reactos/dll/directx/wine/devenum # Synced to WineStaging-3.3 +reactos/dll/directx/wine/devenum # Synced to WineStaging-3.9 reactos/dll/directx/wine/dinput # Synced to WineStaging-3.3 reactos/dll/directx/wine/dinput8 # Synced to WineStaging-3.3 reactos/dll/directx/wine/dmusic # Synced to WineStaging-3.3
6 years, 7 months
1
0
0
0
01/01: [PSDK] Add missing DRV_QUERYFUNCTIONINSTANCEID. CORE-14656
by Amine Khaldi
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e00ccd45518eabafd426b…
commit e00ccd45518eabafd426bbde845be7ceb70201ed Author: Amine Khaldi <amine.khaldi(a)reactos.org> AuthorDate: Sun May 27 03:55:03 2018 +0100 Commit: Amine Khaldi <amine.khaldi(a)reactos.org> CommitDate: Sun May 27 03:55:03 2018 +0100 [PSDK] Add missing DRV_QUERYFUNCTIONINSTANCEID. CORE-14656 --- sdk/include/psdk/mmddk.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/include/psdk/mmddk.h b/sdk/include/psdk/mmddk.h index 70c0a84b98..fdb46d1c32 100644 --- a/sdk/include/psdk/mmddk.h +++ b/sdk/include/psdk/mmddk.h @@ -91,6 +91,7 @@ typedef struct { #define DRV_QUERYSTRINGID (DRV_RESERVED + 14) #define DRV_QUERYSTRINGIDSIZE (DRV_RESERVED + 15) #define DRV_QUERYIDFROMSTRINGID (DRV_RESERVED + 16) +#define DRV_QUERYFUNCTIONINSTANCEID (DRV_RESERVED + 17) #ifdef _WINE #define DRV_QUERYDSOUNDIFACE (DRV_RESERVED + 20) #define DRV_QUERYDSOUNDDESC (DRV_RESERVED + 21)
6 years, 7 months
1
0
0
0
01/01: [D3DX9_24 => 43] Sync with Wine Staging 3.9. CORE-14656
by Amine Khaldi
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=561fd571663a33c781171…
commit 561fd571663a33c7811716fa6ef252c980968cdf Author: Amine Khaldi <amine.khaldi(a)reactos.org> AuthorDate: Sun May 27 03:54:15 2018 +0100 Commit: Amine Khaldi <amine.khaldi(a)reactos.org> CommitDate: Sun May 27 03:54:15 2018 +0100 [D3DX9_24 => 43] Sync with Wine Staging 3.9. CORE-14656 --- dll/directx/wine/d3dx9_36/d3dx9_private.h | 20 + dll/directx/wine/d3dx9_36/effect.c | 689 +++++++++++++++++------------- dll/directx/wine/d3dx9_36/math.c | 30 +- dll/directx/wine/d3dx9_36/mesh.c | 22 +- dll/directx/wine/d3dx9_36/preshader.c | 3 +- dll/directx/wine/d3dx9_36/shader.c | 38 +- dll/directx/wine/d3dx9_36/texture.c | 9 + media/doc/README.WINE | 2 +- 8 files changed, 462 insertions(+), 351 deletions(-) diff --git a/dll/directx/wine/d3dx9_36/d3dx9_private.h b/dll/directx/wine/d3dx9_36/d3dx9_private.h index edb7455a5f..f5b2b4109c 100644 --- a/dll/directx/wine/d3dx9_36/d3dx9_private.h +++ b/dll/directx/wine/d3dx9_36/d3dx9_private.h @@ -24,6 +24,8 @@ #define NONAMELESSUNION #include "wine/debug.h" +#include "wine/heap.h" +#include "wine/rbtree.h" #define COBJMACROS #include "d3dx9.h" @@ -67,6 +69,14 @@ struct pixel_format_desc { void (*to_rgba)(const struct vec4 *src, struct vec4 *dst, const PALETTEENTRY *palette); }; +struct d3dx_include_from_file +{ + ID3DXInclude ID3DXInclude_iface; +}; + +extern CRITICAL_SECTION from_file_mutex DECLSPEC_HIDDEN; +extern const struct ID3DXIncludeVtbl d3dx_include_from_file_vtbl DECLSPEC_HIDDEN; + static inline BOOL is_conversion_from_supported(const struct pixel_format_desc *format) { if (format->type == FORMAT_ARGB || format->type == FORMAT_ARGBF16 @@ -280,6 +290,13 @@ struct d3dx_param_eval ULONG64 *version_counter; }; +struct param_rb_entry +{ + struct wine_rb_entry entry; + char *full_name; + struct d3dx_parameter *param; +}; + struct d3dx_shared_data; struct d3dx_top_level_parameter; @@ -302,6 +319,9 @@ struct d3dx_parameter struct d3dx_parameter *members; char *semantic; + + char *full_name; + struct wine_rb_entry rb_entry; }; struct d3dx_top_level_parameter diff --git a/dll/directx/wine/d3dx9_36/effect.c b/dll/directx/wine/d3dx9_36/effect.c index e2c0ce3728..8c2b499cd7 100644 --- a/dll/directx/wine/d3dx9_36/effect.c +++ b/dll/directx/wine/d3dx9_36/effect.c @@ -20,6 +20,8 @@ #include "config.h" #include "wine/port.h" +#include <stdio.h> + #include "d3dx9_private.h" #include "d3dcompiler.h" @@ -161,6 +163,10 @@ struct d3dx9_base_effect DWORD flags; ULONG64 version_counter; + + struct wine_rb_tree param_tree; + char *full_name_tmp; + unsigned int full_name_tmp_size; }; struct ID3DXEffectImpl @@ -201,12 +207,10 @@ struct ID3DXEffectCompilerImpl { ID3DXEffectCompiler ID3DXEffectCompiler_iface; LONG ref; - - struct d3dx9_base_effect base_effect; }; -static struct d3dx_parameter *get_annotation_by_name(UINT count, struct d3dx_parameter *parameters, - const char *name); +static struct d3dx_parameter *get_annotation_by_name(struct d3dx9_base_effect *base, + unsigned int count, struct d3dx_parameter *parameters, const char *name); static HRESULT d3dx9_parse_state(struct d3dx9_base_effect *base, struct d3dx_state *state, const char *data, const char **ptr, struct d3dx_object *objects); static void free_parameter(struct d3dx_parameter *param, BOOL element, BOOL child); @@ -682,6 +686,8 @@ static void d3dx9_base_effect_cleanup(struct d3dx9_base_effect *base) TRACE("base %p.\n", base); + heap_free(base->full_name_tmp); + if (base->parameters) { for (i = 0; i < base->parameter_count; ++i) @@ -728,13 +734,6 @@ static void free_effect(struct ID3DXEffectImpl *effect) IDirect3DDevice9_Release(effect->device); } -static void free_effect_compiler(struct ID3DXEffectCompilerImpl *compiler) -{ - TRACE("Free effect compiler %p\n", compiler); - - d3dx9_base_effect_cleanup(&compiler->base_effect); -} - static void get_vector(struct d3dx_parameter *param, D3DXVECTOR4 *vector) { UINT i; @@ -814,7 +813,8 @@ static void set_matrix_transpose(struct d3dx_parameter *param, const D3DXMATRIX } } -static struct d3dx_parameter *get_parameter_element_by_name(struct d3dx_parameter *parameter, const char *name) +static struct d3dx_parameter *get_parameter_element_by_name(struct d3dx9_base_effect *base, + struct d3dx_parameter *parameter, const char *name) { UINT element; struct d3dx_parameter *temp_parameter; @@ -835,7 +835,7 @@ static struct d3dx_parameter *get_parameter_element_by_name(struct d3dx_paramete switch (*part++) { case '.': - return get_parameter_by_name(NULL, temp_parameter, part); + return get_parameter_by_name(base, temp_parameter, part); case '\0': TRACE("Returning parameter %p\n", temp_parameter); @@ -851,8 +851,8 @@ static struct d3dx_parameter *get_parameter_element_by_name(struct d3dx_paramete return NULL; } -static struct d3dx_parameter *get_annotation_by_name(UINT count, struct d3dx_parameter *annotations, - const char *name) +static struct d3dx_parameter *get_annotation_by_name(struct d3dx9_base_effect *base, + unsigned int count, struct d3dx_parameter *annotations, const char *name) { UINT i, length; struct d3dx_parameter *temp_parameter; @@ -879,10 +879,10 @@ static struct d3dx_parameter *get_annotation_by_name(UINT count, struct d3dx_par switch (*part++) { case '.': - return get_parameter_by_name(NULL, temp_parameter, part); + return get_parameter_by_name(base, temp_parameter, part); case '[': - return get_parameter_element_by_name(temp_parameter, part); + return get_parameter_element_by_name(base, temp_parameter, part); default: FIXME("Unhandled case \"%c\"\n", *--part); @@ -898,15 +898,57 @@ static struct d3dx_parameter *get_annotation_by_name(UINT count, struct d3dx_par struct d3dx_parameter *get_parameter_by_name(struct d3dx9_base_effect *base, struct d3dx_parameter *parameter, const char *name) { - UINT i, count, length; struct d3dx_parameter *temp_parameter; + unsigned int name_len, param_name_len; + unsigned int i, count, length; + struct wine_rb_entry *entry; + unsigned int full_name_size; const char *part; + char *full_name; TRACE("base %p, parameter %p, name %s\n", base, parameter, debugstr_a(name)); if (!name || !*name) return NULL; + if (!parameter) + { + if ((entry = wine_rb_get(&base->param_tree, name))) + return WINE_RB_ENTRY_VALUE(entry, struct d3dx_parameter, rb_entry); + return NULL; + } + + /* Pass / technique annotations are not in the parameters tree. */ + if (parameter->full_name) + { + name_len = strlen(name); + param_name_len = strlen(parameter->full_name); + full_name_size = name_len + param_name_len + 2; + if (base->full_name_tmp_size < full_name_size) + { + if (!(full_name = heap_realloc(base->full_name_tmp, full_name_size))) + { + ERR("Out of memory.\n"); + return NULL; + } + base->full_name_tmp = full_name; + base->full_name_tmp_size = full_name_size; + } + else + { + full_name = base->full_name_tmp; + } + memcpy(full_name, parameter->full_name, param_name_len); + full_name[param_name_len] = '.'; + memcpy(full_name + param_name_len + 1, name, name_len); + full_name[param_name_len + 1 + name_len] = 0; + + if ((entry = wine_rb_get(&base->param_tree, full_name))) + return WINE_RB_ENTRY_VALUE(entry, struct d3dx_parameter, rb_entry); + return NULL; + } + count = parameter ? parameter->member_count : base->parameter_count; + length = strcspn( name, "[.@" ); part = name + length; @@ -925,18 +967,18 @@ struct d3dx_parameter *get_parameter_by_name(struct d3dx9_base_effect *base, switch (*part++) { case '.': - return get_parameter_by_name(NULL, temp_parameter, part); + return get_parameter_by_name(base, temp_parameter, part); case '@': { struct d3dx_top_level_parameter *top_param = top_level_parameter_from_parameter(temp_parameter); - return parameter ? NULL : get_annotation_by_name(top_param->annotation_count, + return parameter ? NULL : get_annotation_by_name(base, top_param->annotation_count, top_param->annotations, part); } case '[': - return get_parameter_element_by_name(temp_parameter, part); + return get_parameter_element_by_name(base, temp_parameter, part); default: FIXME("Unhandled case \"%c\"\n", *--part); @@ -1460,7 +1502,7 @@ static D3DXHANDLE d3dx9_base_effect_get_annotation_by_name(struct d3dx9_base_eff annotation_count = get_annotation_from_object(base, object, &annotations); - annotation = get_annotation_by_name(annotation_count, annotations, name); + annotation = get_annotation_by_name(base, annotation_count, annotations, name); if (annotation) { TRACE("Returning parameter %p\n", annotation); @@ -1555,13 +1597,16 @@ static HRESULT d3dx9_base_effect_set_value(struct d3dx9_base_effect *base, case D3DXPT_TEXTURECUBE: for (i = 0; i < (param->element_count ? param->element_count : 1); ++i) { - IUnknown *unk = ((IUnknown **)data)[i]; - if (unk) - IUnknown_AddRef(unk); + IUnknown *old_texture = ((IUnknown **)param->data)[i]; + IUnknown *new_texture = ((IUnknown **)data)[i]; - unk = ((IUnknown **)param->data)[i]; - if (unk) - IUnknown_Release(unk); + if (new_texture == old_texture) + continue; + + if (new_texture) + IUnknown_AddRef(new_texture); + if (old_texture) + IUnknown_Release(old_texture); } /* fallthrough */ case D3DXPT_VOID: @@ -3987,37 +4032,44 @@ done: static HRESULT WINAPI ID3DXEffectImpl_FindNextValidTechnique(ID3DXEffect *iface, D3DXHANDLE technique, D3DXHANDLE *next_technique) { - struct ID3DXEffectImpl *This = impl_from_ID3DXEffect(iface); - struct d3dx9_base_effect *base_effect = &This->base_effect; - UINT i = 0; - - TRACE("iface %p, technique %p, next_technique %p\n", iface, technique, next_technique); + struct ID3DXEffectImpl *effect = impl_from_ID3DXEffect(iface); + struct d3dx9_base_effect *base = &effect->base_effect; + struct d3dx_technique *prev_tech, *tech; + unsigned int i; - if (!next_technique) - return D3DERR_INVALIDCALL; + TRACE("iface %p, technique %p, next_technique %p.\n", iface, technique, next_technique); if (technique) { - for (; i < base_effect->technique_count; i++) + if (!(prev_tech = get_valid_technique(base, technique))) + return D3DERR_INVALIDCALL; + + for (i = 0; i < base->technique_count; ++i) { - if (technique == get_technique_handle(&base_effect->techniques[i])) + tech = &base->techniques[i]; + if (tech == prev_tech) { - i++; /* Go to next technique */ + ++i; break; } } } + else + { + i = 0; + } - for (; i < base_effect->technique_count; i++) + for (; i < base->technique_count; ++i) { - if (SUCCEEDED(iface->lpVtbl->ValidateTechnique(iface, get_technique_handle(&base_effect->techniques[i])))) + tech = &base->techniques[i]; + if (SUCCEEDED(ID3DXEffectImpl_ValidateTechnique(iface, get_technique_handle(tech)))) { - *next_technique = get_technique_handle(&base_effect->techniques[i]); + *next_technique = get_technique_handle(tech); return D3D_OK; } } - *next_technique = NULL; + *next_technique = get_technique_handle(&base->techniques[0]); return S_FALSE; } @@ -4150,7 +4202,7 @@ static HRESULT WINAPI ID3DXEffectImpl_Begin(ID3DXEffect *iface, UINT *passes, DW TRACE("iface %p, passes %p, flags %#x.\n", iface, passes, flags); - if (passes && technique) + if (technique) { if (flags & ~(D3DXFX_DONOTSAVESTATE | D3DXFX_DONOTSAVESAMPLERSTATE | D3DXFX_DONOTSAVESHADERSTATE)) WARN("Invalid flags (%#x) specified.\n", flags); @@ -4182,7 +4234,8 @@ static HRESULT WINAPI ID3DXEffectImpl_Begin(ID3DXEffect *iface, UINT *passes, DW ERR("StateBlock Capture failed, hr %#x.\n", hr); } - *passes = technique->pass_count; + if (passes) + *passes = technique->pass_count; effect->started = TRUE; effect->begin_flags = flags; @@ -4302,13 +4355,65 @@ static HRESULT WINAPI ID3DXEffectImpl_GetDevice(ID3DXEffect *iface, struct IDire return S_OK; } +static BOOL param_on_lost_device(void *data, struct d3dx_parameter *param) +{ + struct IDirect3DVolumeTexture9 *volume_texture; + struct IDirect3DCubeTexture9 *cube_texture; + struct IDirect3DTexture9 *texture; + D3DSURFACE_DESC surface_desc; + D3DVOLUME_DESC volume_desc; + + if (param->class == D3DXPC_OBJECT && !param->element_count) + { + switch (param->type) + { + case D3DXPT_TEXTURE: + case D3DXPT_TEXTURE1D: + case D3DXPT_TEXTURE2D: + texture = *(IDirect3DTexture9 **)param->data; + if (!texture) + return FALSE; + IDirect3DTexture9_GetLevelDesc(texture, 0, &surface_desc); + if (surface_desc.Pool != D3DPOOL_DEFAULT) + return FALSE; + break; + case D3DXPT_TEXTURE3D: + volume_texture = *(IDirect3DVolumeTexture9 **)param->data; + if (!volume_texture) + return FALSE; + IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 0, &volume_desc); + if (volume_desc.Pool != D3DPOOL_DEFAULT) + return FALSE; + break; + case D3DXPT_TEXTURECUBE: + cube_texture = *(IDirect3DCubeTexture9 **)param->data; + if (!cube_texture) + return FALSE; + IDirect3DTexture9_GetLevelDesc(cube_texture, 0, &surface_desc); + if (surface_desc.Pool != D3DPOOL_DEFAULT) + return FALSE; + break; + default: + return FALSE; + } + IUnknown_Release(*(IUnknown **)param->data); + *(IUnknown **)param->data = NULL; + } + return FALSE; +} + static HRESULT WINAPI ID3DXEffectImpl_OnLostDevice(ID3DXEffect* iface) { - struct ID3DXEffectImpl *This = impl_from_ID3DXEffect(iface); + struct ID3DXEffectImpl *effect = impl_from_ID3DXEffect(iface); + struct d3dx9_base_effect *base = &effect->base_effect; + unsigned int i; - FIXME("(%p)->(): stub\n", This); + TRACE("iface %p.\n", iface); - return E_NOTIMPL; + for (i = 0; i < base->parameter_count; ++i) + walk_parameter_tree(&base->parameters[i].param, param_on_lost_device, NULL); + + return D3D_OK; } static HRESULT WINAPI ID3DXEffectImpl_OnResetDevice(ID3DXEffect* iface) @@ -4379,7 +4484,7 @@ static HRESULT WINAPI ID3DXEffectImpl_ApplyParameterBlock(ID3DXEffect* iface, D3 return E_NOTIMPL; } -#if _D3DX9_VER >= 26 +#if D3DX_SDK_VERSION >= 26 static HRESULT WINAPI ID3DXEffectImpl_DeleteParameterBlock(ID3DXEffect* iface, D3DXHANDLE parameter_block) { struct ID3DXEffectImpl *This = impl_from_ID3DXEffect(iface); @@ -4398,14 +4503,20 @@ static HRESULT WINAPI ID3DXEffectImpl_CloneEffect(ID3DXEffect *iface, FIXME("(%p)->(%p, %p): stub\n", This, device, effect); if (!effect) - return D3DXERR_INVALIDDATA; + return D3DERR_INVALIDCALL; + + if (This->base_effect.flags & D3DXFX_NOT_CLONEABLE) + return E_FAIL; + + if (!device) + return D3DERR_INVALIDCALL; iface->lpVtbl->AddRef(iface); *effect = iface; return S_OK; } -#if _D3DX9_VER >= 27 +#if D3DX_SDK_VERSION >= 27 static HRESULT WINAPI ID3DXEffectImpl_SetRawValue(ID3DXEffect *iface, D3DXHANDLE parameter, const void *data, UINT byte_offset, UINT bytes) { @@ -4497,11 +4608,11 @@ static const struct ID3DXEffectVtbl ID3DXEffect_Vtbl = ID3DXEffectImpl_BeginParameterBlock, ID3DXEffectImpl_EndParameterBlock, ID3DXEffectImpl_ApplyParameterBlock, -#if _D3DX9_VER >= 26 +#if D3DX_SDK_VERSION >= 26 ID3DXEffectImpl_DeleteParameterBlock, #endif ID3DXEffectImpl_CloneEffect, -#if _D3DX9_VER >= 27 +#if D3DX_SDK_VERSION >= 27 ID3DXEffectImpl_SetRawValue #endif }; @@ -4547,7 +4658,6 @@ static ULONG WINAPI ID3DXEffectCompilerImpl_Release(ID3DXEffectCompiler *iface) if (!ref) { - free_effect_compiler(This); HeapFree(GetProcessHeap(), 0, This); } @@ -4557,547 +4667,435 @@ static ULONG WINAPI ID3DXEffectCompilerImpl_Release(ID3DXEffectCompiler *iface) /*** ID3DXBaseEffect methods ***/ static HRESULT WINAPI ID3DXEffectCompilerImpl_GetDesc(ID3DXEffectCompiler *iface, D3DXEFFECT_DESC *desc) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, desc %p.\n", iface, desc); + FIXME("iface %p, desc %p stub!\n", iface, desc); - return d3dx9_base_effect_get_desc(&compiler->base_effect, desc); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_GetParameterDesc(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXPARAMETER_DESC *desc) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, desc %p stub!\n", iface, parameter, desc); - TRACE("iface %p, parameter %p, desc %p.\n", iface, parameter, desc); - - return d3dx9_base_effect_get_parameter_desc(&compiler->base_effect, parameter, desc); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_GetTechniqueDesc(ID3DXEffectCompiler *iface, D3DXHANDLE technique, D3DXTECHNIQUE_DESC *desc) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, technique %p, desc %p stub!\n", iface, technique, desc); - TRACE("iface %p, technique %p, desc %p.\n", iface, technique, desc); - - return d3dx9_base_effect_get_technique_desc(&compiler->base_effect, technique, desc); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_GetPassDesc(ID3DXEffectCompiler *iface, D3DXHANDLE pass, D3DXPASS_DESC *desc) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, pass %p, desc %p.\n", iface, pass, desc); + FIXME("iface %p, pass %p, desc %p stub!\n", iface, pass, desc); - return d3dx9_base_effect_get_pass_desc(&compiler->base_effect, pass, desc); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_GetFunctionDesc(ID3DXEffectCompiler *iface, D3DXHANDLE shader, D3DXFUNCTION_DESC *desc) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, shader %p, desc %p.\n", iface, shader, desc); + FIXME("iface %p, shader %p, desc %p stub!\n", iface, shader, desc); - return d3dx9_base_effect_get_function_desc(&compiler->base_effect, shader, desc); + return E_NOTIMPL; } static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameter(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, UINT index) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, index %u stub!\n", iface, parameter, index); - TRACE("iface %p, parameter %p, index %u.\n", iface, parameter, index); - - return d3dx9_base_effect_get_parameter(&compiler->base_effect, parameter, index); + return NULL; } static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameterByName(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const char *name) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, name %s.\n", iface, parameter, debugstr_a(name)); + FIXME("iface %p, parameter %p, name %s stub!\n", iface, parameter, debugstr_a(name)); - return d3dx9_base_effect_get_parameter_by_name(&compiler->base_effect, parameter, name); + return NULL; } static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameterBySemantic(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const char *semantic) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, semantic %s.\n", iface, parameter, debugstr_a(semantic)); + FIXME("iface %p, parameter %p, semantic %s stub!\n", iface, parameter, debugstr_a(semantic)); - return d3dx9_base_effect_get_parameter_by_semantic(&compiler->base_effect, parameter, semantic); + return NULL; } static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameterElement(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, UINT index) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, index %u stub!\n", iface, parameter, index); - TRACE("iface %p, parameter %p, index %u.\n", iface, parameter, index); - - return d3dx9_base_effect_get_parameter_element(&compiler->base_effect, parameter, index); + return NULL; } static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetTechnique(ID3DXEffectCompiler *iface, UINT index) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, index %u stub!\n", iface, index); - TRACE("iface %p, index %u.\n", iface, index); - - return d3dx9_base_effect_get_technique(&compiler->base_effect, index); + return NULL; } static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetTechniqueByName(ID3DXEffectCompiler *iface, const char *name) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name)); - TRACE("iface %p, name %s.\n", iface, debugstr_a(name)); - - return d3dx9_base_effect_get_technique_by_name(&compiler->base_effect, name); + return NULL; } static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetPass(ID3DXEffectCompiler *iface, D3DXHANDLE technique, UINT index) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, technique %p, index %u.\n", iface, technique, index); + FIXME("iface %p, technique %p, index %u stub!\n", iface, technique, index); - return d3dx9_base_effect_get_pass(&compiler->base_effect, technique, index); + return NULL; } static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetPassByName(ID3DXEffectCompiler *iface, D3DXHANDLE technique, const char *name) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, technique %p, name %s stub!\n", iface, technique, debugstr_a(name)); - TRACE("iface %p, technique %p, name %s.\n", iface, technique, debugstr_a(name)); - - return d3dx9_base_effect_get_pass_by_name(&compiler->base_effect, technique, name); + return NULL; } static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetFunction(ID3DXEffectCompiler *iface, UINT index) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, index %u stub!\n", iface, index); - TRACE("iface %p, index %u.\n", iface, index); - - return d3dx9_base_effect_get_function(&compiler->base_effect, index); + return NULL; } static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetFunctionByName(ID3DXEffectCompiler *iface, const char *name) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, name %s.\n", iface, debugstr_a(name)); + FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name)); - return d3dx9_base_effect_get_function_by_name(&compiler->base_effect, name); + return NULL; } static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetAnnotation(ID3DXEffectCompiler *iface, D3DXHANDLE object, UINT index) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, object %p, index %u.\n", iface, object, index); + FIXME("iface %p, object %p, index %u stub!\n", iface, object, index); - return d3dx9_base_effect_get_annotation(&compiler->base_effect, object, index); + return NULL; } static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetAnnotationByName(ID3DXEffectCompiler *iface, D3DXHANDLE object, const char *name) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, object %p, name %s stub!\n", iface, object, debugstr_a(name)); - TRACE("iface %p, object %p, name %s.\n", iface, object, debugstr_a(name)); - - return d3dx9_base_effect_get_annotation_by_name(&compiler->base_effect, object, name); + return NULL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_SetValue(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const void *data, UINT bytes) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, data %p, bytes %u.\n", iface, parameter, data, bytes); + FIXME("iface %p, parameter %p, data %p, bytes %u stub!\n", iface, parameter, data, bytes); - return d3dx9_base_effect_set_value(&compiler->base_effect, parameter, data, bytes); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_GetValue(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, void *data, UINT bytes) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, data %p, bytes %u.\n", iface, parameter, data, bytes); + FIXME("iface %p, parameter %p, data %p, bytes %u stub!\n", iface, parameter, data, bytes); - return d3dx9_base_effect_get_value(&compiler->base_effect, parameter, data, bytes); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_SetBool(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL b) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, b %#x.\n", iface, parameter, b); + FIXME("iface %p, parameter %p, b %#x stub!\n", iface, parameter, b); - return d3dx9_base_effect_set_bool(&compiler->base_effect, parameter, b); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_GetBool(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL *b) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, b %p stub!\n", iface, parameter, b); - TRACE("iface %p, parameter %p, b %p.\n", iface, parameter, b); - - return d3dx9_base_effect_get_bool(&compiler->base_effect, parameter, b); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_SetBoolArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const BOOL *b, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, b %p, count %u stub!\n", iface, parameter, b, count); - TRACE("iface %p, parameter %p, b %p, count %u.\n", iface, parameter, b, count); - - return d3dx9_base_effect_set_bool_array(&compiler->base_effect, parameter, b, count); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_GetBoolArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL *b, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, b %p, count %u.\n", iface, parameter, b, count); + FIXME("iface %p, parameter %p, b %p, count %u stub!\n", iface, parameter, b, count); - return d3dx9_base_effect_get_bool_array(&compiler->base_effect, parameter, b, count); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_SetInt(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, INT n) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, n %d.\n", iface, parameter, n); + FIXME("iface %p, parameter %p, n %d stub!\n", iface, parameter, n); - return d3dx9_base_effect_set_int(&compiler->base_effect, parameter, n); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_GetInt(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, INT *n) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, n %p stub!\n", iface, parameter, n); - TRACE("iface %p, parameter %p, n %p.\n", iface, parameter, n); - - return d3dx9_base_effect_get_int(&compiler->base_effect, parameter, n); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_SetIntArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const INT *n, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, n %p, count %u.\n", iface, parameter, n, count); + FIXME("iface %p, parameter %p, n %p, count %u stub!\n", iface, parameter, n, count); - return d3dx9_base_effect_set_int_array(&compiler->base_effect, parameter, n, count); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_GetIntArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, INT *n, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, n %p, count %u.\n", iface, parameter, n, count); + FIXME("iface %p, parameter %p, n %p, count %u stub!\n", iface, parameter, n, count); - return d3dx9_base_effect_get_int_array(&compiler->base_effect, parameter, n, count); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_SetFloat(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, float f) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, f %.8e stub!\n", iface, parameter, f); - TRACE("iface %p, parameter %p, f %.8e.\n", iface, parameter, f); - - return d3dx9_base_effect_set_float(&compiler->base_effect, parameter, f); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_GetFloat(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, float *f) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, f %p stub!\n", iface, parameter, f); - TRACE("iface %p, parameter %p, f %p.\n", iface, parameter, f); - - return d3dx9_base_effect_get_float(&compiler->base_effect, parameter, f); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_SetFloatArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const float *f, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, f %p, count %u stub!\n", iface, parameter, f, count); - TRACE("iface %p, parameter %p, f %p, count %u.\n", iface, parameter, f, count); - - return d3dx9_base_effect_set_float_array(&compiler->base_effect, parameter, f, count); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_GetFloatArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, float *f, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, f %p, count %u.\n", iface, parameter, f, count); + FIXME("iface %p, parameter %p, f %p, count %u stub!\n", iface, parameter, f, count); - return d3dx9_base_effect_get_float_array(&compiler->base_effect, parameter, f, count); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_SetVector(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const D3DXVECTOR4 *vector) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, vector %p stub!\n", iface, parameter, vector); - TRACE("iface %p, parameter %p, vector %p.\n", iface, parameter, vector); - - return d3dx9_base_effect_set_vector(&compiler->base_effect, parameter, vector); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_GetVector(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXVECTOR4 *vector) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, vector %p stub!\n", iface, parameter, vector); - TRACE("iface %p, parameter %p, vector %p.\n", iface, parameter, vector); - - return d3dx9_base_effect_get_vector(&compiler->base_effect, parameter, vector); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_SetVectorArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const D3DXVECTOR4 *vector, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, vector %p, count %u.\n", iface, parameter, vector, count); + FIXME("iface %p, parameter %p, vector %p, count %u stub!\n", iface, parameter, vector, count); - return d3dx9_base_effect_set_vector_array(&compiler->base_effect, parameter, vector, count); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_GetVectorArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXVECTOR4 *vector, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, vector %p, count %u.\n", iface, parameter, vector, count); + FIXME("iface %p, parameter %p, vector %p, count %u stub!\n", iface, parameter, vector, count); - return d3dx9_base_effect_get_vector_array(&compiler->base_effect, parameter, vector, count); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrix(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const D3DXMATRIX *matrix) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, matrix %p stub!\n", iface, parameter, matrix); - TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix); - - return d3dx9_base_effect_set_matrix(&compiler->base_effect, parameter, matrix); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrix(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXMATRIX *matrix) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix); + FIXME("iface %p, parameter %p, matrix %p stub!\n", iface, parameter, matrix); - return d3dx9_base_effect_get_matrix(&compiler->base_effect, parameter, matrix); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const D3DXMATRIX *matrix, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count); + FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count); - return d3dx9_base_effect_set_matrix_array(&compiler->base_effect, parameter, matrix, count); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXMATRIX *matrix, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count); + FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count); - return d3dx9_base_effect_get_matrix_array(&compiler->base_effect, parameter, matrix, count); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixPointerArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const D3DXMATRIX **matrix, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count); - TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count); - - return d3dx9_base_effect_set_matrix_pointer_array(&compiler->base_effect, parameter, matrix, count); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixPointerArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXMATRIX **matrix, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count); - TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count); - - return d3dx9_base_effect_get_matrix_pointer_array(&compiler->base_effect, parameter, matrix, count); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixTranspose(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const D3DXMATRIX *matrix) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix); + FIXME("iface %p, parameter %p, matrix %p stub!\n", iface, parameter, matrix); - return d3dx9_base_effect_set_matrix_transpose(&compiler->base_effect, parameter, matrix); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixTranspose(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXMATRIX *matrix) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix); + FIXME("iface %p, parameter %p, matrix %p stub!\n", iface, parameter, matrix); - return d3dx9_base_effect_get_matrix_transpose(&compiler->base_effect, parameter, matrix); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixTransposeArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const D3DXMATRIX *matrix, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count); - TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count); - - return d3dx9_base_effect_set_matrix_transpose_array(&compiler->base_effect, parameter, matrix, count); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixTransposeArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXMATRIX *matrix, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count); + FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count); - return d3dx9_base_effect_get_matrix_transpose_array(&compiler->base_effect, parameter, matrix, count); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixTransposePointerArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const D3DXMATRIX **matrix, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count); + FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count); - return d3dx9_base_effect_set_matrix_transpose_pointer_array(&compiler->base_effect, parameter, matrix, count); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixTransposePointerArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXMATRIX **matrix, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count); - TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count); - - return d3dx9_base_effect_get_matrix_transpose_pointer_array(&compiler->base_effect, parameter, matrix, count); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_SetString(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const char *string) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, string %s stub!\n", iface, parameter, debugstr_a(string)); - TRACE("iface %p, parameter %p, string %s.\n", iface, parameter, debugstr_a(string)); - - return d3dx9_base_effect_set_string(&compiler->base_effect, parameter, string); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_GetString(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const char **string) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, string %p stub!\n", iface, parameter, string); - TRACE("iface %p, parameter %p, string %p.\n", iface, parameter, string); - - return d3dx9_base_effect_get_string(&compiler->base_effect, parameter, string); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_SetTexture(struct ID3DXEffectCompiler *iface, D3DXHANDLE parameter, struct IDirect3DBaseTexture9 *texture) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, texture %p.\n", iface, parameter, texture); + FIXME("iface %p, parameter %p, texture %p stub!\n", iface, parameter, texture); - return d3dx9_base_effect_set_texture(&compiler->base_effect, parameter, texture); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_GetTexture(struct ID3DXEffectCompiler *iface, D3DXHANDLE parameter, struct IDirect3DBaseTexture9 **texture) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, texture %p stub!\n", iface, parameter, texture); - TRACE("iface %p, parameter %p, texture %p.\n", iface, parameter, texture); - - return d3dx9_base_effect_get_texture(&compiler->base_effect, parameter, texture); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_GetPixelShader(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, struct IDirect3DPixelShader9 **shader) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, shader %p stub!\n", iface, parameter, shader); - TRACE("iface %p, parameter %p, shader %p.\n", iface, parameter, shader); - - return d3dx9_base_effect_get_pixel_shader(&compiler->base_effect, parameter, shader); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_GetVertexShader(struct ID3DXEffectCompiler *iface, D3DXHANDLE parameter, struct IDirect3DVertexShader9 **shader) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, shader %p.\n", iface, parameter, shader); + FIXME("iface %p, parameter %p, shader %p stub!\n", iface, parameter, shader); - return d3dx9_base_effect_get_vertex_shader(&compiler->base_effect, parameter, shader); + return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_SetArrayRange(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, UINT start, UINT end) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, start %u, end %u.\n", iface, parameter, start, end); + FIXME("iface %p, parameter %p, start %u, end %u stub!\n", iface, parameter, start, end); - return d3dx9_base_effect_set_array_range(&compiler->base_effect, parameter, start, end); + return E_NOTIMPL; } /*** ID3DXEffectCompiler methods ***/ static HRESULT WINAPI ID3DXEffectCompilerImpl_SetLiteral(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL literal) { - struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface); - - FIXME("iface %p, parameter %p, literal %u\n", This, parameter, literal); + FIXME("iface %p, parameter %p, literal %#x stub!\n", iface, parameter, literal); return E_NOTIMPL; } static HRESULT WINAPI ID3DXEffectCompilerImpl_GetLiteral(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL *literal) { - struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface); - - FIXME("iface %p, parameter %p, literal %p\n", This, parameter, literal); + FIXME("iface %p, parameter %p, literal %p stub!\n", iface, parameter, literal); return E_NOTIMPL; } @@ -5105,9 +5103,7 @@ static HRESULT WINAPI ID3DXEffectCompilerImpl_GetLiteral(ID3DXEffectCompiler *if static HRESULT WINAPI ID3DXEffectCompilerImpl_CompileEffect(ID3DXEffectCompiler *iface, DWORD flags, ID3DXBuffer **effect, ID3DXBuffer **error_msgs) { - struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface); - - FIXME("iface %p, flags %#x, effect %p, error_msgs %p stub\n", This, flags, effect, error_msgs); + FIXME("iface %p, flags %#x, effect %p, error_msgs %p stub!\n", iface, flags, effect, error_msgs); return E_NOTIMPL; } @@ -5116,10 +5112,8 @@ static HRESULT WINAPI ID3DXEffectCompilerImpl_CompileShader(ID3DXEffectCompiler const char *target, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_msgs, ID3DXConstantTable **constant_table) { - struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface); - - FIXME("iface %p, function %p, target %p, flags %#x, shader %p, error_msgs %p, constant_table %p stub\n", - This, function, target, flags, shader, error_msgs, constant_table); + FIXME("iface %p, function %p, target %s, flags %#x, shader %p, error_msgs %p, constant_table %p stub!\n", + iface, function, debugstr_a(target), flags, shader, error_msgs, constant_table); return E_NOTIMPL; } @@ -5457,6 +5451,83 @@ static void param_set_magic_number(struct d3dx_parameter *param) memcpy(param->magic_string, parameter_magic_string, sizeof(parameter_magic_string)); } +static int param_rb_compare(const void *key, const struct wine_rb_entry *entry) +{ + const char *name = key; + struct d3dx_parameter *param = WINE_RB_ENTRY_VALUE(entry, struct d3dx_parameter, rb_entry); + + return strcmp(name, param->full_name); +} + +static void add_param_to_tree(struct d3dx9_base_effect *base, struct d3dx_parameter *param, + struct d3dx_parameter *parent, char separator, unsigned int element) +{ + const char *parent_name = parent ? parent->full_name : NULL; + unsigned int i; + + TRACE("Adding parameter %p (%s - parent %p, element %u) to the rbtree.\n", + param, debugstr_a(param->name), parent, element); + + if (parent_name) + { + unsigned int parent_name_len = strlen(parent_name); + unsigned int name_len = strlen(param->name); + unsigned int part_str_len; + unsigned int len; + char part_str[16]; + + if (separator == '[') + { + sprintf(part_str, "[%u]", element); + part_str_len = strlen(part_str); + name_len = 0; + } + else + { + part_str[0] = separator; + part_str[1] = 0; + part_str_len = 1; + } + len = parent_name_len + part_str_len + name_len + 1; + + if (!(param->full_name = heap_alloc(len))) + { + ERR("Out of memory.\n"); + return; + } + + memcpy(param->full_name, parent_name, parent_name_len); + memcpy(param->full_name + parent_name_len, part_str, part_str_len); + memcpy(param->full_name + parent_name_len + part_str_len, param->name, name_len); + param->full_name[len - 1] = 0; + } + else + { + unsigned int len = strlen(param->name) + 1; + + if (!(param->full_name = heap_alloc(len))) + { + ERR("Out of memory.\n"); + return; + } + + memcpy(param->full_name, param->name, len); + } + TRACE("Full name is %s.\n", param->full_name); + wine_rb_put(&base->param_tree, param->full_name, ¶m->rb_entry); + + if (is_top_level_parameter(param)) + for (i = 0; i < param->top_level_param->annotation_count; ++i) + add_param_to_tree(base, ¶m->top_level_param->annotations[i], param, '@', 0); + + if (param->element_count) + for (i = 0; i < param->element_count; ++i) + add_param_to_tree(base, ¶m->members[i], param, '[', i); + else + for (i = 0; i < param->member_count; ++i) + add_param_to_tree(base, ¶m->members[i], param, '.', 0); +} + static HRESULT d3dx9_parse_effect_typedef(struct d3dx9_base_effect *base, struct d3dx_parameter *param, const char *data, const char **ptr, struct d3dx_parameter *parent, UINT flags) { @@ -6302,6 +6373,7 @@ static HRESULT d3dx9_parse_effect(struct d3dx9_base_effect *base, const char *da goto err_out; } + wine_rb_init(&base->param_tree, param_rb_compare); if (base->parameter_count) { base->parameters = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, @@ -6324,6 +6396,7 @@ static HRESULT d3dx9_parse_effect(struct d3dx9_base_effect *base, const char *da } walk_parameter_tree(&base->parameters[i].param, param_set_top_level_param, &base->parameters[i]); + add_param_to_tree(base, &base->parameters[i].param, NULL, 0, 0); } } @@ -6503,8 +6576,10 @@ static HRESULT d3dx9_base_effect_init(struct d3dx9_base_effect *base, #endif unsigned int i, j; - TRACE("base %p, data %p, data_size %lu, effect %p, pool %p, skip_constants %s.\n", - base, data, data_size, effect, pool, debugstr_a(skip_constants_string)); + TRACE("base %p, data %p, data_size %lu, defines %p, include %p, eflags %#x, errors %p, " + "effect %p, pool %p, skip_constants %s.\n", + base, data, data_size, defines, include, eflags, errors, effect, pool, + debugstr_a(skip_constants_string)); base->effect = effect; base->pool = pool; @@ -6517,7 +6592,7 @@ static HRESULT d3dx9_base_effect_init(struct d3dx9_base_effect *base, { TRACE("HLSL ASCII effect, trying to compile it.\n"); hr = D3DCompile(data, data_size, NULL, defines, include, - "main", "fx_2_0", compile_flags, eflags, &bytecode, &temp_errors); + NULL, "fx_2_0", compile_flags, eflags, &bytecode, &temp_errors); if (FAILED(hr)) { WARN("Failed to compile ASCII effect.\n"); @@ -6726,20 +6801,13 @@ static HRESULT d3dx9_effect_compiler_init(struct ID3DXEffectCompilerImpl *compil const char *data, SIZE_T data_size, const D3D_SHADER_MACRO *defines, ID3DInclude *include, UINT eflags, ID3DBlob **error_messages) { - HRESULT hr; - - TRACE("effect %p, data %p, data_size %lu\n", compiler, data, data_size); + TRACE("compiler %p, data %p, data_size %lu, defines %p, include %p, eflags %#x, error_messages %p.\n", + compiler, data, data_size, defines, include, eflags, error_messages); compiler->ID3DXEffectCompiler_iface.lpVtbl = &ID3DXEffectCompiler_Vtbl; compiler->ref = 1; - if (FAILED(hr = d3dx9_base_effect_init(&compiler->base_effect, data, data_size, defines, - include, eflags, error_messages, NULL, NULL, NULL))) - { - FIXME("Failed to parse effect, hr %#x.\n", hr); - free_effect_compiler(compiler); - return hr; - } + FIXME("ID3DXEffectCompiler implementation is only a stub.\n"); return D3D_OK; } @@ -6880,9 +6948,11 @@ HRESULT WINAPI D3DXCreateEffectFromFileExW(struct IDirect3DDevice9 *device, cons const D3DXMACRO *defines, struct ID3DXInclude *include, const char *skipconstants, DWORD flags, struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **compilationerrors) { - void *buffer; + struct d3dx_include_from_file include_from_file; + const void *buffer; + unsigned int size; + char *filename_a; HRESULT ret; - DWORD size; TRACE("device %p, srcfile %s, defines %p, include %p, skipconstants %s, " "flags %#x, pool %p, effect %p, compilationerrors %p.\n", @@ -6892,14 +6962,33 @@ HRESULT WINAPI D3DXCreateEffectFromFileExW(struct IDirect3DDevice9 *device, cons if (!device || !srcfile) return D3DERR_INVALIDCALL; - ret = map_view_of_file(srcfile, &buffer, &size); + if (!include) + { + include_from_file.ID3DXInclude_iface.lpVtbl = &d3dx_include_from_file_vtbl; + include = &include_from_file.ID3DXInclude_iface; + } + size = WideCharToMultiByte(CP_ACP, 0, srcfile, -1, NULL, 0, NULL, NULL); + filename_a = heap_alloc(size); + if (!filename_a) + return E_OUTOFMEMORY; + WideCharToMultiByte(CP_ACP, 0, srcfile, -1, filename_a, size, NULL, NULL); + + EnterCriticalSection(&from_file_mutex); + ret = ID3DXInclude_Open(include, D3DXINC_LOCAL, filename_a, NULL, &buffer, &size); if (FAILED(ret)) + { + LeaveCriticalSection(&from_file_mutex); + heap_free(filename_a); return D3DXERR_INVALIDDATA; + } - ret = D3DXCreateEffectEx(device, buffer, size, defines, include, skipconstants, flags, pool, effect, compilationerrors); - UnmapViewOfFile(buffer); + ret = D3DXCreateEffectEx(device, buffer, size, defines, include, skipconstants, flags, pool, + effect, compilationerrors); + ID3DXInclude_Close(include, buffer); + LeaveCriticalSection(&from_file_mutex); + heap_free(filename_a); return ret; } diff --git a/dll/directx/wine/d3dx9_36/math.c b/dll/directx/wine/d3dx9_36/math.c index 856e987cb9..8909c3c6b2 100644 --- a/dll/directx/wine/d3dx9_36/math.c +++ b/dll/directx/wine/d3dx9_36/math.c @@ -1987,27 +1987,33 @@ D3DXVECTOR3* WINAPI D3DXVec3TransformNormalArray(D3DXVECTOR3* out, UINT outstrid return out; } -D3DXVECTOR3* WINAPI D3DXVec3Unproject(D3DXVECTOR3 *pout, const D3DXVECTOR3 *pv, const D3DVIEWPORT9 *pviewport, const D3DXMATRIX *pprojection, const D3DXMATRIX *pview, const D3DXMATRIX *pworld) +D3DXVECTOR3 * WINAPI D3DXVec3Unproject(D3DXVECTOR3 *out, const D3DXVECTOR3 *v, + const D3DVIEWPORT9 *viewport, const D3DXMATRIX *projection, const D3DXMATRIX *view, + const D3DXMATRIX *world) { D3DXMATRIX m; - TRACE("pout %p, pv %p, pviewport %p, pprojection %p, pview %p, pworlds %p\n", pout, pv, pviewport, pprojection, pview, pworld); + TRACE("out %p, v %p, viewport %p, projection %p, view %p, world %p.\n", + out, v, viewport, projection, view, world); D3DXMatrixIdentity(&m); - if (pworld) D3DXMatrixMultiply(&m, &m, pworld); - if (pview) D3DXMatrixMultiply(&m, &m, pview); - if (pprojection) D3DXMatrixMultiply(&m, &m, pprojection); + if (world) + D3DXMatrixMultiply(&m, &m, world); + if (view) + D3DXMatrixMultiply(&m, &m, view); + if (projection) + D3DXMatrixMultiply(&m, &m, projection); D3DXMatrixInverse(&m, NULL, &m); - *pout = *pv; - if (pviewport) + *out = *v; + if (viewport) { - pout->x = 2.0f * ( pout->x - pviewport->X ) / pviewport->Width - 1.0f; - pout->y = 1.0f - 2.0f * ( pout->y - pviewport->Y ) / pviewport->Height; - pout->z = ( pout->z - pviewport->MinZ) / ( pviewport->MaxZ - pviewport->MinZ ); + out->x = 2.0f * (out->x - viewport->X) / viewport->Width - 1.0f; + out->y = 1.0f - 2.0f * (out->y - viewport->Y) / viewport->Height; + out->z = (out->z - viewport->MinZ) / (viewport->MaxZ - viewport->MinZ); } - D3DXVec3TransformCoord(pout, pout, &m); - return pout; + D3DXVec3TransformCoord(out, out, &m); + return out; } D3DXVECTOR3* WINAPI D3DXVec3UnprojectArray(D3DXVECTOR3* out, UINT outstride, const D3DXVECTOR3* in, UINT instride, const D3DVIEWPORT9* viewport, const D3DXMATRIX* projection, const D3DXMATRIX* view, const D3DXMATRIX* world, UINT elements) diff --git a/dll/directx/wine/d3dx9_36/mesh.c b/dll/directx/wine/d3dx9_36/mesh.c index 3dd881ee1c..204e0b5e86 100644 --- a/dll/directx/wine/d3dx9_36/mesh.c +++ b/dll/directx/wine/d3dx9_36/mesh.c @@ -4568,7 +4568,7 @@ HRESULT WINAPI D3DXCreatePolygon(struct IDirect3DDevice9 *device, float length, struct vertex *vertices; WORD (*faces)[3]; DWORD (*adjacency_buf)[3]; - float scale; + float angle, scale; unsigned int i; TRACE("device %p, length %f, sides %u, mesh %p, adjacency %p.\n", @@ -4596,7 +4596,9 @@ HRESULT WINAPI D3DXCreatePolygon(struct IDirect3DDevice9 *device, float length, return hr; } - scale = 0.5f * length / sinf(D3DX_PI / sides); + angle = D3DX_PI / sides; + scale = 0.5f * length / sinf(angle); + angle *= 2.0f; vertices[0].position.x = 0.0f; vertices[0].position.y = 0.0f; @@ -4607,8 +4609,8 @@ HRESULT WINAPI D3DXCreatePolygon(struct IDirect3DDevice9 *device, float length, for (i = 0; i < sides; ++i) { - vertices[i + 1].position.x = cosf(2.0f * D3DX_PI * i / sides) * scale; - vertices[i + 1].position.y = sinf(2.0f * D3DX_PI * i / sides) * scale; + vertices[i + 1].position.x = cosf(angle * i) * scale; + vertices[i + 1].position.y = sinf(angle * i) * scale; vertices[i + 1].position.z = 0.0f; vertices[i + 1].normal.x = 0.0f; vertices[i + 1].normal.y = 0.0f; @@ -7574,18 +7576,6 @@ HRESULT WINAPI D3DXComputeNormals(struct ID3DXBaseMesh *mesh, const DWORD *adjac adjacency, -1.01f, -0.01f, -1.01f, NULL, NULL); } -/************************************************************************* - * D3DXComputeNormalMap (D3DX9_36.@) - */ -HRESULT WINAPI D3DXComputeNormalMap(IDirect3DTexture9 *texture, IDirect3DTexture9 *src_texture, - const PALETTEENTRY *src_palette, DWORD flags, DWORD channel, FLOAT amplitude) -{ - FIXME("texture %p, src_texture %p, src_palette %p, flags %#x, channel %u, amplitude %f stub.\n", - texture, src_texture, src_palette, flags, channel, amplitude); - - return D3D_OK; -} - /************************************************************************* * D3DXIntersect (D3DX9_36.@) */ diff --git a/dll/directx/wine/d3dx9_36/preshader.c b/dll/directx/wine/d3dx9_36/preshader.c index ef27149d82..9a1562a548 100644 --- a/dll/directx/wine/d3dx9_36/preshader.c +++ b/dll/directx/wine/d3dx9_36/preshader.c @@ -1213,7 +1213,8 @@ static HRESULT parse_preshader(struct d3dx_preshader *pres, unsigned int *ptr, u } if (reg_idx >= pres->regs.table_sizes[table]) { - FIXME("Out of bounds register index, i %u, j %u, table %u, reg_idx %u.\n", + /* Native accepts these broken preshaders. */ + FIXME("Out of bounds register index, i %u, j %u, table %u, reg_idx %u, preshader parsing failed.\n", i, j, table, reg_idx); return D3DXERR_INVALIDDATA; } diff --git a/dll/directx/wine/d3dx9_36/shader.c b/dll/directx/wine/d3dx9_36/shader.c index 2bbc6b79e0..d3f6570f9f 100644 --- a/dll/directx/wine/d3dx9_36/shader.c +++ b/dll/directx/wine/d3dx9_36/shader.c @@ -216,7 +216,6 @@ HRESULT WINAPI D3DXAssembleShader(const char *data, UINT data_len, const D3DXMAC static const void *main_file_data; -static CRITICAL_SECTION from_file_mutex; static CRITICAL_SECTION_DEBUG from_file_mutex_debug = { 0, 0, &from_file_mutex, @@ -226,14 +225,14 @@ static CRITICAL_SECTION_DEBUG from_file_mutex_debug = }, 0, 0, {(DWORD_PTR)(__FILE__ ": from_file_mutex")} }; -static CRITICAL_SECTION from_file_mutex = {&from_file_mutex_debug, -1, 0, 0, 0, 0}; +CRITICAL_SECTION from_file_mutex = {&from_file_mutex_debug, -1, 0, 0, 0, 0}; /* D3DXInclude private implementation, used to implement * D3DXAssembleShaderFromFile() from D3DXAssembleShader(). */ /* To be able to correctly resolve include search paths we have to store the * pathname of each include file. We store the pathname pointer right before * the file data. */ -static HRESULT WINAPI d3dincludefromfile_open(ID3DXInclude *iface, D3DXINCLUDE_TYPE include_type, +static HRESULT WINAPI d3dx_include_from_file_open(ID3DXInclude *iface, D3DXINCLUDE_TYPE include_type, const char *filename, const void *parent_data, const void **data, UINT *bytes) { const char *p, *parent_name = ""; @@ -252,7 +251,7 @@ static HRESULT WINAPI d3dincludefromfile_open(ID3DXInclude *iface, D3DXINCLUDE_T parent_name = *((const char **)main_file_data - 1); } - TRACE("Looking up for include file %s, parent %s\n", debugstr_a(filename), debugstr_a(parent_name)); + TRACE("Looking up include file %s, parent %s.\n", debugstr_a(filename), debugstr_a(parent_name)); if ((p = strrchr(parent_name, '\\'))) ++p; @@ -303,7 +302,7 @@ error: return HRESULT_FROM_WIN32(GetLastError()); } -static HRESULT WINAPI d3dincludefromfile_close(ID3DXInclude *iface, const void *data) +static HRESULT WINAPI d3dx_include_from_file_close(ID3DXInclude *iface, const void *data) { HeapFree(GetProcessHeap(), 0, *((char **)data - 1)); HeapFree(GetProcessHeap(), 0, (char **)data - 1); @@ -312,13 +311,10 @@ static HRESULT WINAPI d3dincludefromfile_close(ID3DXInclude *iface, const void * return S_OK; } -static const struct ID3DXIncludeVtbl D3DXInclude_Vtbl = { - d3dincludefromfile_open, - d3dincludefromfile_close -}; - -struct D3DXIncludeImpl { - ID3DXInclude ID3DXInclude_iface; +const struct ID3DXIncludeVtbl d3dx_include_from_file_vtbl = +{ + d3dx_include_from_file_open, + d3dx_include_from_file_close }; HRESULT WINAPI D3DXAssembleShaderFromFileA(const char *filename, const D3DXMACRO *defines, @@ -350,7 +346,7 @@ HRESULT WINAPI D3DXAssembleShaderFromFileW(const WCHAR *filename, const D3DXMACR const void *buffer; DWORD len; HRESULT hr; - struct D3DXIncludeImpl includefromfile; + struct d3dx_include_from_file include_from_file; char *filename_a; TRACE("filename %s, defines %p, include %p, flags %#x, shader %p, error_messages %p.\n", @@ -358,8 +354,8 @@ HRESULT WINAPI D3DXAssembleShaderFromFileW(const WCHAR *filename, const D3DXMACR if(!include) { - includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl; - include = &includefromfile.ID3DXInclude_iface; + include_from_file.ID3DXInclude_iface.lpVtbl = &d3dx_include_from_file_vtbl; + include = &include_from_file.ID3DXInclude_iface; } len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL); @@ -518,7 +514,7 @@ HRESULT WINAPI D3DXCompileShaderFromFileW(const WCHAR *filename, const D3DXMACRO const void *buffer; DWORD len, filename_len; HRESULT hr; - struct D3DXIncludeImpl includefromfile; + struct d3dx_include_from_file include_from_file; char *filename_a; TRACE("filename %s, defines %p, include %p, entrypoint %s, profile %s, " @@ -528,8 +524,8 @@ HRESULT WINAPI D3DXCompileShaderFromFileW(const WCHAR *filename, const D3DXMACRO if (!include) { - includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl; - include = &includefromfile.ID3DXInclude_iface; + include_from_file.ID3DXInclude_iface.lpVtbl = &d3dx_include_from_file_vtbl; + include = &include_from_file.ID3DXInclude_iface; } filename_len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL); @@ -643,7 +639,7 @@ HRESULT WINAPI D3DXPreprocessShaderFromFileW(const WCHAR *filename, const D3DXMA const void *buffer; DWORD len; HRESULT hr; - struct D3DXIncludeImpl includefromfile; + struct d3dx_include_from_file include_from_file; char *filename_a; TRACE("filename %s, defines %p, include %p, shader %p, error_messages %p.\n", @@ -651,8 +647,8 @@ HRESULT WINAPI D3DXPreprocessShaderFromFileW(const WCHAR *filename, const D3DXMA if (!include) { - includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl; - include = &includefromfile.ID3DXInclude_iface; + include_from_file.ID3DXInclude_iface.lpVtbl = &d3dx_include_from_file_vtbl; + include = &include_from_file.ID3DXInclude_iface; } len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL); diff --git a/dll/directx/wine/d3dx9_36/texture.c b/dll/directx/wine/d3dx9_36/texture.c index fa5ccfc66e..7a84d8c12a 100644 --- a/dll/directx/wine/d3dx9_36/texture.c +++ b/dll/directx/wine/d3dx9_36/texture.c @@ -1916,3 +1916,12 @@ HRESULT WINAPI D3DXSaveTextureToFileInMemory(ID3DXBuffer **dst_buffer, D3DXIMAGE return hr; } + +HRESULT WINAPI D3DXComputeNormalMap(IDirect3DTexture9 *texture, IDirect3DTexture9 *src_texture, + const PALETTEENTRY *src_palette, DWORD flags, DWORD channel, float amplitude) +{ + FIXME("texture %p, src_texture %p, src_palette %p, flags %#x, channel %u, amplitude %.8e stub.\n", + texture, src_texture, src_palette, flags, channel, amplitude); + + return D3D_OK; +} diff --git a/media/doc/README.WINE b/media/doc/README.WINE index 2e0303348c..477bb4d3e3 100644 --- a/media/doc/README.WINE +++ b/media/doc/README.WINE @@ -26,7 +26,7 @@ reactos/dll/directx/wine/d3d8 # Synced to WineStaging-3.9 reactos/dll/directx/wine/d3d9 # Synced to WineStaging-3.9 reactos/dll/directx/wine/d3dcompiler_43 # Synced to WineStaging-3.3 reactos/dll/directx/wine/d3drm # Synced to WineStaging-3.9 -reactos/dll/directx/wine/d3dx9_24 => 43 # Synced to WineStaging-3.3 +reactos/dll/directx/wine/d3dx9_24 => 43 # Synced to WineStaging-3.9 reactos/dll/directx/wine/d3dxof # Synced to WineStaging-3.3 reactos/dll/directx/wine/ddraw # Synced to WineStaging-3.9 reactos/dll/directx/wine/devenum # Synced to WineStaging-3.3
6 years, 7 months
1
0
0
0
01/01: [D3DRM] Sync with Wine Staging 3.9. CORE-14656
by Amine Khaldi
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=61ea4c528e724bf3c1825…
commit 61ea4c528e724bf3c1825a1b642deb72021195a8 Author: Amine Khaldi <amine.khaldi(a)reactos.org> AuthorDate: Sun May 27 03:53:02 2018 +0100 Commit: Amine Khaldi <amine.khaldi(a)reactos.org> CommitDate: Sun May 27 03:53:02 2018 +0100 [D3DRM] Sync with Wine Staging 3.9. CORE-14656 --- dll/directx/wine/d3drm/viewport.c | 6 +++--- media/doc/README.WINE | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dll/directx/wine/d3drm/viewport.c b/dll/directx/wine/d3drm/viewport.c index 37c70c8db2..5c0e24bc42 100644 --- a/dll/directx/wine/d3drm/viewport.c +++ b/dll/directx/wine/d3drm/viewport.c @@ -339,6 +339,9 @@ static HRESULT WINAPI d3drm_viewport2_Init(IDirect3DRMViewport2 *iface, IDirect3 if (FAILED(hr = IDirect3D_CreateViewport(d3d1, &viewport->d3d_viewport, NULL))) goto cleanup; + if (FAILED(hr = IDirect3DDevice_AddViewport(d3d_device, viewport->d3d_viewport))) + goto cleanup; + vp.dwSize = sizeof(vp); vp.dwWidth = width; vp.dwHeight = height; @@ -355,9 +358,6 @@ static HRESULT WINAPI d3drm_viewport2_Init(IDirect3DRMViewport2 *iface, IDirect3 if (FAILED(hr = IDirect3DViewport_SetViewport(viewport->d3d_viewport, &vp))) goto cleanup; - if (FAILED(hr = IDirect3DDevice_AddViewport(d3d_device, viewport->d3d_viewport))) - goto cleanup; - if (FAILED(hr = IDirect3DRMFrame3_QueryInterface(camera, &IID_IDirect3DRMFrame, (void **)&viewport->camera))) goto cleanup; diff --git a/media/doc/README.WINE b/media/doc/README.WINE index 1847393ab6..2e0303348c 100644 --- a/media/doc/README.WINE +++ b/media/doc/README.WINE @@ -25,7 +25,7 @@ reactos/dll/directx/wine/amstream # Synced to WineStaging-3.9 reactos/dll/directx/wine/d3d8 # Synced to WineStaging-3.9 reactos/dll/directx/wine/d3d9 # Synced to WineStaging-3.9 reactos/dll/directx/wine/d3dcompiler_43 # Synced to WineStaging-3.3 -reactos/dll/directx/wine/d3drm # Synced to WineStaging-3.3 +reactos/dll/directx/wine/d3drm # Synced to WineStaging-3.9 reactos/dll/directx/wine/d3dx9_24 => 43 # Synced to WineStaging-3.3 reactos/dll/directx/wine/d3dxof # Synced to WineStaging-3.3 reactos/dll/directx/wine/ddraw # Synced to WineStaging-3.9
6 years, 7 months
1
0
0
0
01/01: [D3D8][D3D9][DDRAW][WINED3D] Sync with Wine Staging 3.9. CORE-14656
by Amine Khaldi
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7af3969e9fe68b5f55a08…
commit 7af3969e9fe68b5f55a088f93a6b69570822c733 Author: Amine Khaldi <amine.khaldi(a)reactos.org> AuthorDate: Sun May 27 03:52:04 2018 +0100 Commit: Amine Khaldi <amine.khaldi(a)reactos.org> CommitDate: Sun May 27 03:52:04 2018 +0100 [D3D8][D3D9][DDRAW][WINED3D] Sync with Wine Staging 3.9. CORE-14656 --- dll/directx/wine/d3d8/d3d8_private.h | 3 +- dll/directx/wine/d3d8/device.c | 201 +- dll/directx/wine/d3d8/directx.c | 2 +- dll/directx/wine/d3d8/swapchain.c | 9 +- dll/directx/wine/d3d9/d3d9_private.h | 6 +- dll/directx/wine/d3d9/device.c | 189 +- dll/directx/wine/d3d9/directx.c | 8 +- dll/directx/wine/d3d9/swapchain.c | 34 +- dll/directx/wine/d3d9/texture.c | 17 +- dll/directx/wine/ddraw/ddraw.c | 49 +- dll/directx/wine/ddraw/ddraw_private.h | 7 +- dll/directx/wine/ddraw/device.c | 56 +- dll/directx/wine/ddraw/executebuffer.c | 23 +- dll/directx/wine/ddraw/palette.c | 2 +- dll/directx/wine/ddraw/surface.c | 71 +- dll/directx/wine/ddraw/utils.c | 4 +- dll/directx/wine/ddraw/viewport.c | 257 +-- dll/directx/wine/wined3d/arb_program_shader.c | 359 ++-- dll/directx/wine/wined3d/ati_fragment_shader.c | 37 +- dll/directx/wine/wined3d/buffer.c | 10 +- dll/directx/wine/wined3d/context.c | 1402 ++++++++++---- dll/directx/wine/wined3d/cs.c | 180 +- dll/directx/wine/wined3d/device.c | 373 ++-- dll/directx/wine/wined3d/directx.c | 88 +- dll/directx/wine/wined3d/glsl_shader.c | 1159 +++++++++++- dll/directx/wine/wined3d/nvidia_texture_shader.c | 3 + dll/directx/wine/wined3d/resource.c | 25 +- dll/directx/wine/wined3d/shader.c | 230 ++- dll/directx/wine/wined3d/shader_sm4.c | 79 +- dll/directx/wine/wined3d/state.c | 888 ++------- dll/directx/wine/wined3d/stateblock.c | 34 +- dll/directx/wine/wined3d/surface.c | 1252 ++++--------- dll/directx/wine/wined3d/swapchain.c | 111 +- dll/directx/wine/wined3d/texture.c | 2188 ++++++++++------------ dll/directx/wine/wined3d/utils.c | 149 +- dll/directx/wine/wined3d/view.c | 18 +- dll/directx/wine/wined3d/wined3d.spec | 16 +- dll/directx/wine/wined3d/wined3d_gl.h | 3 +- dll/directx/wine/wined3d/wined3d_main.c | 15 +- dll/directx/wine/wined3d/wined3d_private.h | 313 ++-- media/doc/README.WINE | 8 +- sdk/include/reactos/wine/wined3d.h | 74 +- 42 files changed, 5257 insertions(+), 4695 deletions(-) diff --git a/dll/directx/wine/d3d8/d3d8_private.h b/dll/directx/wine/d3d8/d3d8_private.h index cba5dd647b..3fbc096b25 100644 --- a/dll/directx/wine/d3d8/d3d8_private.h +++ b/dll/directx/wine/d3d8/d3d8_private.h @@ -166,10 +166,11 @@ struct d3d8_swapchain LONG refcount; struct wined3d_swapchain *wined3d_swapchain; IDirect3DDevice8 *parent_device; + unsigned int swap_interval; }; HRESULT d3d8_swapchain_create(struct d3d8_device *device, struct wined3d_swapchain_desc *desc, - struct d3d8_swapchain **swapchain) DECLSPEC_HIDDEN; + unsigned int swap_interval, struct d3d8_swapchain **swapchain) DECLSPEC_HIDDEN; struct d3d8_surface { diff --git a/dll/directx/wine/d3d8/device.c b/dll/directx/wine/d3d8/device.c index 5daf6f46c2..616886bcaf 100644 --- a/dll/directx/wine/d3d8/device.c +++ b/dll/directx/wine/d3d8/device.c @@ -209,7 +209,7 @@ static D3DSWAPEFFECT d3dswapeffect_from_wined3dswapeffect(enum wined3d_swap_effe } static void present_parameters_from_wined3d_swapchain_desc(D3DPRESENT_PARAMETERS *present_parameters, - const struct wined3d_swapchain_desc *swapchain_desc) + const struct wined3d_swapchain_desc *swapchain_desc, DWORD presentation_interval) { present_parameters->BackBufferWidth = swapchain_desc->backbuffer_width; present_parameters->BackBufferHeight = swapchain_desc->backbuffer_height; @@ -224,7 +224,7 @@ static void present_parameters_from_wined3d_swapchain_desc(D3DPRESENT_PARAMETERS = d3dformat_from_wined3dformat(swapchain_desc->auto_depth_stencil_format); present_parameters->Flags = swapchain_desc->flags & D3DPRESENTFLAGS_MASK; present_parameters->FullScreen_RefreshRateInHz = swapchain_desc->refresh_rate; - present_parameters->FullScreen_PresentationInterval = swapchain_desc->swap_interval; + present_parameters->FullScreen_PresentationInterval = presentation_interval; } static enum wined3d_swap_effect wined3dswapeffect_from_d3dswapeffect(D3DSWAPEFFECT effect) @@ -245,6 +245,27 @@ static enum wined3d_swap_effect wined3dswapeffect_from_d3dswapeffect(D3DSWAPEFFE } } +static enum wined3d_swap_interval wined3dswapinterval_from_d3d(DWORD interval) +{ + switch (interval) + { + case D3DPRESENT_INTERVAL_IMMEDIATE: + return WINED3D_SWAP_INTERVAL_IMMEDIATE; + case D3DPRESENT_INTERVAL_ONE: + return WINED3D_SWAP_INTERVAL_ONE; + case D3DPRESENT_INTERVAL_TWO: + return WINED3D_SWAP_INTERVAL_TWO; + case D3DPRESENT_INTERVAL_THREE: + return WINED3D_SWAP_INTERVAL_THREE; + case D3DPRESENT_INTERVAL_FOUR: + return WINED3D_SWAP_INTERVAL_FOUR; + default: + FIXME("Unhandled presentation interval %#x.\n", interval); + case D3DPRESENT_INTERVAL_DEFAULT: + return WINED3D_SWAP_INTERVAL_DEFAULT; + } +} + static BOOL wined3d_swapchain_desc_from_present_parameters(struct wined3d_swapchain_desc *swapchain_desc, const D3DPRESENT_PARAMETERS *present_parameters) { @@ -261,6 +282,20 @@ static BOOL wined3d_swapchain_desc_from_present_parameters(struct wined3d_swapch WARN("Invalid backbuffer count %u.\n", present_parameters->BackBufferCount); return FALSE; } + switch (present_parameters->FullScreen_PresentationInterval) + { + case D3DPRESENT_INTERVAL_DEFAULT: + case D3DPRESENT_INTERVAL_ONE: + case D3DPRESENT_INTERVAL_TWO: + case D3DPRESENT_INTERVAL_THREE: + case D3DPRESENT_INTERVAL_FOUR: + case D3DPRESENT_INTERVAL_IMMEDIATE: + break; + default: + WARN("Invalid presentation interval %#x.\n", + present_parameters->FullScreen_PresentationInterval); + return FALSE; + } swapchain_desc->backbuffer_width = present_parameters->BackBufferWidth; swapchain_desc->backbuffer_height = present_parameters->BackBufferHeight; @@ -278,7 +313,6 @@ static BOOL wined3d_swapchain_desc_from_present_parameters(struct wined3d_swapch swapchain_desc->flags = (present_parameters->Flags & D3DPRESENTFLAGS_MASK) | WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH; swapchain_desc->refresh_rate = present_parameters->FullScreen_RefreshRateInHz; - swapchain_desc->swap_interval = present_parameters->FullScreen_PresentationInterval; swapchain_desc->auto_restore_display_mode = TRUE; if (present_parameters->Flags & ~D3DPRESENTFLAGS_MASK) @@ -294,7 +328,7 @@ void d3dcaps_from_wined3dcaps(D3DCAPS8 *caps, const WINED3DCAPS *wined3d_caps) caps->Caps = wined3d_caps->Caps; caps->Caps2 = wined3d_caps->Caps2; caps->Caps3 = wined3d_caps->Caps3; - caps->PresentationIntervals = wined3d_caps->PresentationIntervals; + caps->PresentationIntervals = D3DPRESENT_INTERVAL_IMMEDIATE | D3DPRESENT_INTERVAL_ONE; caps->CursorCaps = wined3d_caps->CursorCaps; caps->DevCaps = wined3d_caps->DevCaps; caps->PrimitiveMiscCaps = wined3d_caps->PrimitiveMiscCaps; @@ -343,6 +377,57 @@ void d3dcaps_from_wined3dcaps(D3DCAPS8 *caps, const WINED3DCAPS *wined3d_caps) caps->PixelShaderVersion = wined3d_caps->PixelShaderVersion; caps->MaxPixelShaderValue = wined3d_caps->PixelShader1xMaxValue; + caps->Caps2 &= D3DCAPS2_CANCALIBRATEGAMMA | D3DCAPS2_CANRENDERWINDOWED + | D3DCAPS2_CANMANAGERESOURCE | D3DCAPS2_DYNAMICTEXTURES | D3DCAPS2_FULLSCREENGAMMA + | D3DCAPS2_NO2DDURING3DSCENE | D3DCAPS2_RESERVED; + caps->Caps3 &= D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD | D3DCAPS3_RESERVED; + caps->PrimitiveMiscCaps &= D3DPMISCCAPS_MASKZ | D3DPMISCCAPS_LINEPATTERNREP + | D3DPMISCCAPS_CULLNONE | D3DPMISCCAPS_CULLCW | D3DPMISCCAPS_CULLCCW + | D3DPMISCCAPS_COLORWRITEENABLE | D3DPMISCCAPS_CLIPPLANESCALEDPOINTS + | D3DPMISCCAPS_CLIPTLVERTS | D3DPMISCCAPS_TSSARGTEMP | D3DPMISCCAPS_BLENDOP + | D3DPMISCCAPS_NULLREFERENCE; + caps->RasterCaps &= D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_PAT | D3DPRASTERCAPS_ZTEST + | D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_FOGTABLE | D3DPRASTERCAPS_ANTIALIASEDGES + | D3DPRASTERCAPS_MIPMAPLODBIAS | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZBUFFERLESSHSR + | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_ANISOTROPY | D3DPRASTERCAPS_WBUFFER + | D3DPRASTERCAPS_WFOG | D3DPRASTERCAPS_ZFOG | D3DPRASTERCAPS_COLORPERSPECTIVE + | D3DPRASTERCAPS_STRETCHBLTMULTISAMPLE; + caps->SrcBlendCaps &= D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR + | D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA + | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR + | D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA + | D3DPBLENDCAPS_BOTHINVSRCALPHA; + caps->DestBlendCaps &= D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR + | D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA + | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR + | D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA + | D3DPBLENDCAPS_BOTHINVSRCALPHA; + caps->TextureCaps &= D3DPTEXTURECAPS_PERSPECTIVE | D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_ALPHA + | D3DPTEXTURECAPS_SQUAREONLY | D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE + | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_NONPOW2CONDITIONAL + | D3DPTEXTURECAPS_PROJECTED | D3DPTEXTURECAPS_CUBEMAP | D3DPTEXTURECAPS_VOLUMEMAP + | D3DPTEXTURECAPS_MIPMAP | D3DPTEXTURECAPS_MIPVOLUMEMAP | D3DPTEXTURECAPS_MIPCUBEMAP + | D3DPTEXTURECAPS_CUBEMAP_POW2 | D3DPTEXTURECAPS_VOLUMEMAP_POW2; + caps->TextureFilterCaps &= D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR + | D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MIPFPOINT + | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MAGFLINEAR + | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFAFLATCUBIC + | D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC; + caps->CubeTextureFilterCaps &= D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR + | D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MIPFPOINT + | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MAGFLINEAR + | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFAFLATCUBIC + | D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC; + caps->VolumeTextureFilterCaps &= D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR + | D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MIPFPOINT + | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MAGFLINEAR + | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFAFLATCUBIC + | D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC; + caps->StencilCaps &= ~WINED3DSTENCILCAPS_TWOSIDED; + caps->VertexProcessingCaps &= D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 + | D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER + | D3DVTXPCAPS_TWEENING | D3DVTXPCAPS_NO_VSDT_UBYTE4; + /* D3D8 doesn't support SM 2.0 or higher, so clamp to 1.x */ if (caps->PixelShaderVersion) caps->PixelShaderVersion = D3DPS_VERSION(1, 4); @@ -353,8 +438,6 @@ void d3dcaps_from_wined3dcaps(D3DCAPS8 *caps, const WINED3DCAPS *wined3d_caps) else caps->VertexShaderVersion = D3DVS_VERSION(0, 0); caps->MaxVertexShaderConst = min(D3D8_MAX_VERTEX_SHADER_CONSTANTF, caps->MaxVertexShaderConst); - - caps->StencilCaps &= ~WINED3DSTENCILCAPS_TWOSIDED; } /* Handle table functions */ @@ -698,7 +781,8 @@ static HRESULT WINAPI d3d8_device_CreateAdditionalSwapChain(IDirect3DDevice8 *if struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); struct wined3d_swapchain_desc desc; struct d3d8_swapchain *object; - UINT i, count; + unsigned int swap_interval; + unsigned int i, count; HRESULT hr; TRACE("iface %p, present_parameters %p, swapchain %p.\n", @@ -730,9 +814,11 @@ static HRESULT WINAPI d3d8_device_CreateAdditionalSwapChain(IDirect3DDevice8 *if if (!wined3d_swapchain_desc_from_present_parameters(&desc, present_parameters)) return D3DERR_INVALIDCALL; - if (SUCCEEDED(hr = d3d8_swapchain_create(device, &desc, &object))) + swap_interval = wined3dswapinterval_from_d3d(present_parameters->FullScreen_PresentationInterval); + if (SUCCEEDED(hr = d3d8_swapchain_create(device, &desc, swap_interval, &object))) *swapchain = &object->IDirect3DSwapChain8_iface; - present_parameters_from_wined3d_swapchain_desc(present_parameters, &desc); + present_parameters_from_wined3d_swapchain_desc(present_parameters, + &desc, present_parameters->FullScreen_PresentationInterval); return hr; } @@ -806,6 +892,8 @@ static HRESULT WINAPI d3d8_device_Reset(IDirect3DDevice8 *iface, NULL, reset_enum_callback, TRUE))) { present_parameters->BackBufferCount = swapchain_desc.backbuffer_count; + device->implicit_swapchain->swap_interval + = wined3dswapinterval_from_d3d(present_parameters->FullScreen_PresentationInterval); wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_POINTSIZE_MIN, 0); wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_ZENABLE, !!swapchain_desc.enable_auto_depth_stencil); @@ -1531,10 +1619,30 @@ static HRESULT WINAPI d3d8_device_MultiplyTransform(IDirect3DDevice8 *iface, static HRESULT WINAPI d3d8_device_SetViewport(IDirect3DDevice8 *iface, const D3DVIEWPORT8 *viewport) { struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct wined3d_sub_resource_desc rt_desc; + struct wined3d_rendertarget_view *rtv; + struct d3d8_surface *surface; struct wined3d_viewport vp; TRACE("iface %p, viewport %p.\n", iface, viewport); + wined3d_mutex_lock(); + if (!(rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0))) + { + wined3d_mutex_unlock(); + return D3DERR_NOTFOUND; + } + surface = wined3d_rendertarget_view_get_sub_resource_parent(rtv); + wined3d_texture_get_sub_resource_desc(surface->wined3d_texture, surface->sub_resource_idx, &rt_desc); + + if (viewport->X > rt_desc.width || viewport->Width > rt_desc.width - viewport->X + || viewport->Y > rt_desc.height || viewport->Height > rt_desc.height - viewport->Y) + { + WARN("Invalid viewport, returning D3DERR_INVALIDCALL.\n"); + wined3d_mutex_unlock(); + return D3DERR_INVALIDCALL; + } + vp.x = viewport->X; vp.y = viewport->Y; vp.width = viewport->Width; @@ -1542,8 +1650,7 @@ static HRESULT WINAPI d3d8_device_SetViewport(IDirect3DDevice8 *iface, const D3D vp.min_z = viewport->MinZ; vp.max_z = viewport->MaxZ; - wined3d_mutex_lock(); - wined3d_device_set_viewport(device->wined3d_device, &vp); + wined3d_device_set_viewports(device->wined3d_device, 1, &vp); wined3d_mutex_unlock(); return D3D_OK; @@ -1557,7 +1664,7 @@ static HRESULT WINAPI d3d8_device_GetViewport(IDirect3DDevice8 *iface, D3DVIEWPO TRACE("iface %p, viewport %p.\n", iface, viewport); wined3d_mutex_lock(); - wined3d_device_get_viewport(device->wined3d_device, &wined3d_viewport); + wined3d_device_get_viewports(device->wined3d_device, NULL, &wined3d_viewport); wined3d_mutex_unlock(); viewport->X = wined3d_viewport.x; @@ -2080,9 +2187,11 @@ static HRESULT WINAPI d3d8_device_ValidateDevice(IDirect3DDevice8 *iface, DWORD static HRESULT WINAPI d3d8_device_GetInfo(IDirect3DDevice8 *iface, DWORD info_id, void *info, DWORD info_size) { - FIXME("iface %p, info_id %#x, info %p, info_size %u stub!\n", iface, info_id, info, info_size); + TRACE("iface %p, info_id %#x, info %p, info_size %u.\n", iface, info_id, info, info_size); - return D3D_OK; + if (info_id < 4) + return E_FAIL; + return S_FALSE; } static HRESULT WINAPI d3d8_device_SetPaletteEntries(IDirect3DDevice8 *iface, @@ -3162,40 +3271,40 @@ static void CDECL device_parent_activate(struct wined3d_device_parent *device_pa InterlockedCompareExchange(&device->device_state, D3D8_DEVICE_STATE_NOT_RESET, D3D8_DEVICE_STATE_LOST); } -static HRESULT CDECL device_parent_surface_created(struct wined3d_device_parent *device_parent, - struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx, +static HRESULT CDECL device_parent_texture_sub_resource_created(struct wined3d_device_parent *device_parent, + enum wined3d_resource_type type, struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx, void **parent, const struct wined3d_parent_ops **parent_ops) { - struct d3d8_surface *d3d_surface; + TRACE("device_parent %p, type %#x, wined3d_texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n", + device_parent, type, wined3d_texture, sub_resource_idx, parent, parent_ops); - TRACE("device_parent %p, wined3d_texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n", - device_parent, wined3d_texture, sub_resource_idx, parent, parent_ops); - - if (!(d3d_surface = heap_alloc_zero(sizeof(*d3d_surface)))) - return E_OUTOFMEMORY; - - surface_init(d3d_surface, wined3d_texture, sub_resource_idx, parent_ops); - *parent = d3d_surface; - TRACE("Created surface %p.\n", d3d_surface); - - return D3D_OK; -} + if (type == WINED3D_RTYPE_TEXTURE_2D) + { + struct d3d8_surface *d3d_surface; -static HRESULT CDECL device_parent_volume_created(struct wined3d_device_parent *device_parent, - struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx, - void **parent, const struct wined3d_parent_ops **parent_ops) -{ - struct d3d8_volume *d3d_volume; + if (!(d3d_surface = heap_alloc_zero(sizeof(*d3d_surface)))) + return E_OUTOFMEMORY; - TRACE("device_parent %p, texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n", - device_parent, wined3d_texture, sub_resource_idx, parent, parent_ops); + surface_init(d3d_surface, wined3d_texture, sub_resource_idx, parent_ops); + *parent = d3d_surface; + TRACE("Created surface %p.\n", d3d_surface); + } + else if (type == WINED3D_RTYPE_TEXTURE_3D) + { + struct d3d8_volume *d3d_volume; - if (!(d3d_volume = heap_alloc_zero(sizeof(*d3d_volume)))) - return E_OUTOFMEMORY; + if (!(d3d_volume = heap_alloc_zero(sizeof(*d3d_volume)))) + return E_OUTOFMEMORY; - volume_init(d3d_volume, wined3d_texture, sub_resource_idx, parent_ops); - *parent = d3d_volume; - TRACE("Created volume %p.\n", d3d_volume); + volume_init(d3d_volume, wined3d_texture, sub_resource_idx, parent_ops); + *parent = d3d_volume; + TRACE("Created volume %p.\n", d3d_volume); + } + else + { + ERR("Unhandled resource type %#x.\n", type); + return E_FAIL; + } return D3D_OK; } @@ -3234,7 +3343,7 @@ static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent TRACE("device_parent %p, desc %p, swapchain %p.\n", device_parent, desc, swapchain); - if (FAILED(hr = d3d8_swapchain_create(device, desc, &d3d_swapchain))) + if (FAILED(hr = d3d8_swapchain_create(device, desc, WINED3D_SWAP_INTERVAL_DEFAULT, &d3d_swapchain))) { WARN("Failed to create swapchain, hr %#x.\n", hr); *swapchain = NULL; @@ -3253,8 +3362,7 @@ static const struct wined3d_device_parent_ops d3d8_wined3d_device_parent_ops = device_parent_wined3d_device_created, device_parent_mode_changed, device_parent_activate, - device_parent_surface_created, - device_parent_volume_created, + device_parent_texture_sub_resource_created, device_parent_create_swapchain_texture, device_parent_create_swapchain, }; @@ -3356,7 +3464,8 @@ HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wine wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_POINTSIZE_MIN, 0); wined3d_mutex_unlock(); - present_parameters_from_wined3d_swapchain_desc(parameters, &swapchain_desc); + present_parameters_from_wined3d_swapchain_desc(parameters, + &swapchain_desc, parameters->FullScreen_PresentationInterval); device->declArraySize = 16; if (!(device->decls = heap_alloc(device->declArraySize * sizeof(*device->decls)))) @@ -3368,6 +3477,8 @@ HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wine wined3d_swapchain = wined3d_device_get_swapchain(device->wined3d_device, 0); device->implicit_swapchain = wined3d_swapchain_get_parent(wined3d_swapchain); + device->implicit_swapchain->swap_interval + = wined3dswapinterval_from_d3d(parameters->FullScreen_PresentationInterval); device->d3d_parent = &parent->IDirect3D8_iface; IDirect3D8_AddRef(device->d3d_parent); diff --git a/dll/directx/wine/d3d8/directx.c b/dll/directx/wine/d3d8/directx.c index 6e8f93a25c..68300c0a65 100644 --- a/dll/directx/wine/d3d8/directx.c +++ b/dll/directx/wine/d3d8/directx.c @@ -417,7 +417,7 @@ BOOL d3d8_init(struct d3d8 *d3d8) DWORD flags = WINED3D_LEGACY_DEPTH_BIAS | WINED3D_VIDMEM_ACCOUNTING | WINED3D_HANDLE_RESTORE | WINED3D_PIXEL_CENTER_INTEGER | WINED3D_LEGACY_UNBOUND_RESOURCE_COLOR | WINED3D_NO_PRIMITIVE_RESTART - | WINED3D_LEGACY_CUBEMAP_FILTERING | WINED3D_LIMIT_VIEWPORT; + | WINED3D_LEGACY_CUBEMAP_FILTERING; d3d8->IDirect3D8_iface.lpVtbl = &d3d8_vtbl; d3d8->refcount = 1; diff --git a/dll/directx/wine/d3d8/swapchain.c b/dll/directx/wine/d3d8/swapchain.c index 3a588b5e8c..39e3b23873 100644 --- a/dll/directx/wine/d3d8/swapchain.c +++ b/dll/directx/wine/d3d8/swapchain.c @@ -105,7 +105,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d8_swapchain_Present(IDirect3DSwapChai wined3d_mutex_lock(); hr = wined3d_swapchain_present(swapchain->wined3d_swapchain, - src_rect, dst_rect, dst_window_override, 0, 0); + src_rect, dst_rect, dst_window_override, swapchain->swap_interval, 0); wined3d_mutex_unlock(); return hr; @@ -167,12 +167,13 @@ static const struct wined3d_parent_ops d3d8_swapchain_wined3d_parent_ops = }; static HRESULT swapchain_init(struct d3d8_swapchain *swapchain, struct d3d8_device *device, - struct wined3d_swapchain_desc *desc) + struct wined3d_swapchain_desc *desc, unsigned int swap_interval) { HRESULT hr; swapchain->refcount = 1; swapchain->IDirect3DSwapChain8_iface.lpVtbl = &d3d8_swapchain_vtbl; + swapchain->swap_interval = swap_interval; wined3d_mutex_lock(); hr = wined3d_swapchain_create(device->wined3d_device, desc, swapchain, @@ -192,7 +193,7 @@ static HRESULT swapchain_init(struct d3d8_swapchain *swapchain, struct d3d8_devi } HRESULT d3d8_swapchain_create(struct d3d8_device *device, struct wined3d_swapchain_desc *desc, - struct d3d8_swapchain **swapchain) + unsigned int swap_interval, struct d3d8_swapchain **swapchain) { struct d3d8_swapchain *object; HRESULT hr; @@ -200,7 +201,7 @@ HRESULT d3d8_swapchain_create(struct d3d8_device *device, struct wined3d_swapcha if (!(object = heap_alloc_zero(sizeof(*object)))) return E_OUTOFMEMORY; - if (FAILED(hr = swapchain_init(object, device, desc))) + if (FAILED(hr = swapchain_init(object, device, desc, swap_interval))) { WARN("Failed to initialize swapchain, hr %#x.\n", hr); heap_free(object); diff --git a/dll/directx/wine/d3d9/d3d9_private.h b/dll/directx/wine/d3d9/d3d9_private.h index ba19e5fb08..c50aabf593 100644 --- a/dll/directx/wine/d3d9/d3d9_private.h +++ b/dll/directx/wine/d3d9/d3d9_private.h @@ -57,7 +57,7 @@ BOOL is_gdi_compat_wined3dformat(enum wined3d_format_id format) DECLSPEC_HIDDEN; enum wined3d_format_id wined3dformat_from_d3dformat(D3DFORMAT format) DECLSPEC_HIDDEN; unsigned int wined3dmapflags_from_d3dmapflags(unsigned int flags) DECLSPEC_HIDDEN; void present_parameters_from_wined3d_swapchain_desc(D3DPRESENT_PARAMETERS *present_parameters, - const struct wined3d_swapchain_desc *swapchain_desc) DECLSPEC_HIDDEN; + const struct wined3d_swapchain_desc *swapchain_desc, DWORD presentation_interval) DECLSPEC_HIDDEN; void d3dcaps_from_wined3dcaps(D3DCAPS9 *caps, const WINED3DCAPS *wined3d_caps) DECLSPEC_HIDDEN; struct d3d9 @@ -101,7 +101,6 @@ struct d3d9_device UINT index_buffer_size; UINT index_buffer_pos; - struct d3d9_texture *textures[D3D9_MAX_TEXTURE_UNITS]; struct d3d9_surface *render_targets[D3D_MAX_SIMULTANEOUS_RENDERTARGETS]; LONG device_state; @@ -151,10 +150,11 @@ struct d3d9_swapchain LONG refcount; struct wined3d_swapchain *wined3d_swapchain; IDirect3DDevice9Ex *parent_device; + unsigned int swap_interval; }; HRESULT d3d9_swapchain_create(struct d3d9_device *device, struct wined3d_swapchain_desc *desc, - struct d3d9_swapchain **swapchain) DECLSPEC_HIDDEN; + unsigned int swap_interval, struct d3d9_swapchain **swapchain) DECLSPEC_HIDDEN; struct d3d9_surface { diff --git a/dll/directx/wine/d3d9/device.c b/dll/directx/wine/d3d9/device.c index bc73699e52..2f3ad2880d 100644 --- a/dll/directx/wine/d3d9/device.c +++ b/dll/directx/wine/d3d9/device.c @@ -231,7 +231,7 @@ static D3DSWAPEFFECT d3dswapeffect_from_wined3dswapeffect(enum wined3d_swap_effe } void present_parameters_from_wined3d_swapchain_desc(D3DPRESENT_PARAMETERS *present_parameters, - const struct wined3d_swapchain_desc *swapchain_desc) + const struct wined3d_swapchain_desc *swapchain_desc, DWORD presentation_interval) { present_parameters->BackBufferWidth = swapchain_desc->backbuffer_width; present_parameters->BackBufferHeight = swapchain_desc->backbuffer_height; @@ -247,7 +247,7 @@ void present_parameters_from_wined3d_swapchain_desc(D3DPRESENT_PARAMETERS *prese = d3dformat_from_wined3dformat(swapchain_desc->auto_depth_stencil_format); present_parameters->Flags = swapchain_desc->flags & D3DPRESENTFLAGS_MASK; present_parameters->FullScreen_RefreshRateInHz = swapchain_desc->refresh_rate; - present_parameters->PresentationInterval = swapchain_desc->swap_interval; + present_parameters->PresentationInterval = presentation_interval; } static enum wined3d_swap_effect wined3dswapeffect_from_d3dswapeffect(D3DSWAPEFFECT effect) @@ -270,6 +270,27 @@ static enum wined3d_swap_effect wined3dswapeffect_from_d3dswapeffect(D3DSWAPEFFE } } +static enum wined3d_swap_interval wined3dswapinterval_from_d3d(DWORD interval) +{ + switch (interval) + { + case D3DPRESENT_INTERVAL_IMMEDIATE: + return WINED3D_SWAP_INTERVAL_IMMEDIATE; + case D3DPRESENT_INTERVAL_ONE: + return WINED3D_SWAP_INTERVAL_ONE; + case D3DPRESENT_INTERVAL_TWO: + return WINED3D_SWAP_INTERVAL_TWO; + case D3DPRESENT_INTERVAL_THREE: + return WINED3D_SWAP_INTERVAL_THREE; + case D3DPRESENT_INTERVAL_FOUR: + return WINED3D_SWAP_INTERVAL_FOUR; + default: + FIXME("Unhandled presentation interval %#x.\n", interval); + case D3DPRESENT_INTERVAL_DEFAULT: + return WINED3D_SWAP_INTERVAL_DEFAULT; + } +} + static BOOL wined3d_swapchain_desc_from_present_parameters(struct wined3d_swapchain_desc *swapchain_desc, const D3DPRESENT_PARAMETERS *present_parameters, BOOL extended) { @@ -288,6 +309,19 @@ static BOOL wined3d_swapchain_desc_from_present_parameters(struct wined3d_swapch WARN("Invalid backbuffer count %u.\n", present_parameters->BackBufferCount); return FALSE; } + switch (present_parameters->PresentationInterval) + { + case D3DPRESENT_INTERVAL_DEFAULT: + case D3DPRESENT_INTERVAL_ONE: + case D3DPRESENT_INTERVAL_TWO: + case D3DPRESENT_INTERVAL_THREE: + case D3DPRESENT_INTERVAL_FOUR: + case D3DPRESENT_INTERVAL_IMMEDIATE: + break; + default: + WARN("Invalid presentation interval %#x.\n", present_parameters->PresentationInterval); + return FALSE; + } swapchain_desc->backbuffer_width = present_parameters->BackBufferWidth; swapchain_desc->backbuffer_height = present_parameters->BackBufferHeight; @@ -305,7 +339,6 @@ static BOOL wined3d_swapchain_desc_from_present_parameters(struct wined3d_swapch swapchain_desc->flags = (present_parameters->Flags & D3DPRESENTFLAGS_MASK) | WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH; swapchain_desc->refresh_rate = present_parameters->FullScreen_RefreshRateInHz; - swapchain_desc->swap_interval = present_parameters->PresentationInterval; swapchain_desc->auto_restore_display_mode = TRUE; if (present_parameters->Flags & ~D3DPRESENTFLAGS_MASK) @@ -330,7 +363,7 @@ void d3dcaps_from_wined3dcaps(D3DCAPS9 *caps, const WINED3DCAPS *wined3d_caps) caps->Caps = wined3d_caps->Caps; caps->Caps2 = wined3d_caps->Caps2; caps->Caps3 = wined3d_caps->Caps3; - caps->PresentationIntervals = wined3d_caps->PresentationIntervals; + caps->PresentationIntervals = D3DPRESENT_INTERVAL_IMMEDIATE | D3DPRESENT_INTERVAL_ONE; caps->CursorCaps = wined3d_caps->CursorCaps; caps->DevCaps = wined3d_caps->DevCaps; caps->PrimitiveMiscCaps = wined3d_caps->PrimitiveMiscCaps; @@ -743,7 +776,8 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_CreateAdditionalSwapChain(ID struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); struct wined3d_swapchain_desc desc; struct d3d9_swapchain *object; - UINT i, count; + unsigned int swap_interval; + unsigned int i, count; HRESULT hr; TRACE("iface %p, present_parameters %p, swapchain %p.\n", @@ -776,9 +810,11 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_CreateAdditionalSwapChain(ID if (!wined3d_swapchain_desc_from_present_parameters(&desc, present_parameters, device->d3d_parent->extended)) return D3DERR_INVALIDCALL; - if (SUCCEEDED(hr = d3d9_swapchain_create(device, &desc, &object))) + swap_interval = wined3dswapinterval_from_d3d(present_parameters->PresentationInterval); + if (SUCCEEDED(hr = d3d9_swapchain_create(device, &desc, swap_interval, &object))) *swapchain = (IDirect3DSwapChain9 *)&object->IDirect3DSwapChain9Ex_iface; - present_parameters_from_wined3d_swapchain_desc(present_parameters, &desc); + present_parameters_from_wined3d_swapchain_desc(present_parameters, + &desc, present_parameters->PresentationInterval); return hr; } @@ -934,6 +970,8 @@ static HRESULT d3d9_device_reset(struct d3d9_device *device, } else { + device->implicit_swapchains[0]->swap_interval + = wined3dswapinterval_from_d3d(present_parameters->PresentationInterval); wined3d_swapchain_get_desc(device->implicit_swapchains[0]->wined3d_swapchain, &swapchain_desc); present_parameters->BackBufferWidth = swapchain_desc.backbuffer_width; present_parameters->BackBufferHeight = swapchain_desc.backbuffer_height; @@ -943,10 +981,6 @@ static HRESULT d3d9_device_reset(struct d3d9_device *device, device->device_state = D3D9_DEVICE_STATE_OK; } - if (!device->d3d_parent->extended) - for (i = 0; i < ARRAY_SIZE(device->textures); ++i) - device->textures[i] = NULL; - rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0); device->render_targets[0] = wined3d_rendertarget_view_get_sub_resource_parent(rtv); for (i = 1; i < ARRAY_SIZE(device->render_targets); ++i) @@ -976,7 +1010,8 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_Present(IDirect3DDevice9Ex * const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, const RGNDATA *dirty_region) { struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); - UINT i; + struct d3d9_swapchain *swapchain; + unsigned int i; HRESULT hr; TRACE("iface %p, src_rect %p, dst_rect %p, dst_window_override %p, dirty_region %p.\n", @@ -991,8 +1026,9 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_Present(IDirect3DDevice9Ex * wined3d_mutex_lock(); for (i = 0; i < device->implicit_swapchain_count; ++i) { - if (FAILED(hr = wined3d_swapchain_present(device->implicit_swapchains[i]->wined3d_swapchain, - src_rect, dst_rect, dst_window_override, 0, 0))) + swapchain = device->implicit_swapchains[i]; + if (FAILED(hr = wined3d_swapchain_present(swapchain->wined3d_swapchain, + src_rect, dst_rect, dst_window_override, swapchain->swap_interval, 0))) { wined3d_mutex_unlock(); return hr; @@ -1500,7 +1536,7 @@ static HRESULT WINAPI d3d9_device_UpdateSurface(IDirect3DDevice9Ex *iface, hr = wined3d_device_copy_sub_resource_region(device->wined3d_device, wined3d_texture_get_resource(dst->wined3d_texture), dst->sub_resource_idx, dst_point ? dst_point->x : 0, dst_point ? dst_point->y : 0, 0, wined3d_texture_get_resource(src->wined3d_texture), - src->sub_resource_idx, &src_box); + src->sub_resource_idx, &src_box, 0); if (SUCCEEDED(hr) && dst->texture) d3d9_texture_flag_auto_gen_mipmap(dst->texture); @@ -2032,7 +2068,7 @@ static HRESULT WINAPI d3d9_device_SetViewport(IDirect3DDevice9Ex *iface, const D vp.max_z = viewport->MaxZ; wined3d_mutex_lock(); - wined3d_device_set_viewport(device->wined3d_device, &vp); + wined3d_device_set_viewports(device->wined3d_device, 1, &vp); wined3d_mutex_unlock(); return D3D_OK; @@ -2046,7 +2082,7 @@ static HRESULT WINAPI d3d9_device_GetViewport(IDirect3DDevice9Ex *iface, D3DVIEW TRACE("iface %p, viewport %p.\n", iface, viewport); wined3d_mutex_lock(); - wined3d_device_get_viewport(device->wined3d_device, &wined3d_viewport); + wined3d_device_get_viewports(device->wined3d_device, NULL, &wined3d_viewport); wined3d_mutex_unlock(); viewport->X = wined3d_viewport.x; @@ -2362,13 +2398,6 @@ static HRESULT WINAPI d3d9_device_SetTexture(IDirect3DDevice9Ex *iface, DWORD st wined3d_mutex_lock(); hr = wined3d_device_set_texture(device->wined3d_device, stage, texture_impl ? texture_impl->wined3d_texture : NULL); - if (SUCCEEDED(hr)) - { - unsigned int i = stage >= D3DVERTEXTEXTURESAMPLER0 ? stage - D3DVERTEXTEXTURESAMPLER0 + 16 : stage; - - if (stage < ARRAY_SIZE(device->textures)) - device->textures[i] = texture_impl; - } wined3d_mutex_unlock(); return hr; @@ -2535,7 +2564,7 @@ static HRESULT WINAPI d3d9_device_SetScissorRect(IDirect3DDevice9Ex *iface, cons TRACE("iface %p, rect %p.\n", iface, rect); wined3d_mutex_lock(); - wined3d_device_set_scissor_rect(device->wined3d_device, rect); + wined3d_device_set_scissor_rects(device->wined3d_device, 1, rect); wined3d_mutex_unlock(); return D3D_OK; @@ -2548,7 +2577,7 @@ static HRESULT WINAPI d3d9_device_GetScissorRect(IDirect3DDevice9Ex *iface, RECT TRACE("iface %p, rect %p.\n", iface, rect); wined3d_mutex_lock(); - wined3d_device_get_scissor_rect(device->wined3d_device, rect); + wined3d_device_get_scissor_rects(device->wined3d_device, NULL, rect); wined3d_mutex_unlock(); return D3D_OK; @@ -2612,11 +2641,15 @@ static float WINAPI d3d9_device_GetNPatchMode(IDirect3DDevice9Ex *iface) /* wined3d critical section must be taken by the caller. */ static void d3d9_generate_auto_mipmaps(struct d3d9_device *device) { - unsigned int i; + struct wined3d_texture *texture; + unsigned int i, stage; - for (i = 0; i < ARRAY_SIZE(device->textures); ++i) - if (device->textures[i]) - d3d9_texture_gen_auto_mipmap(device->textures[i]); + for (i = 0; i < D3D9_MAX_TEXTURE_UNITS; ++i) + { + stage = i >= 16 ? i - 16 + D3DVERTEXTEXTURESAMPLER0 : i; + if ((texture = wined3d_device_get_texture(device->wined3d_device, stage))) + d3d9_texture_gen_auto_mipmap(wined3d_texture_get_parent(texture)); + } } static HRESULT WINAPI d3d9_device_DrawPrimitive(IDirect3DDevice9Ex *iface, @@ -3667,7 +3700,8 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_PresentEx(IDirect3DDevice9Ex const RGNDATA *dirty_region, DWORD flags) { struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); - UINT i; + struct d3d9_swapchain *swapchain; + unsigned int i; HRESULT hr; TRACE("iface %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p, flags %#x.\n", @@ -3683,8 +3717,9 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_PresentEx(IDirect3DDevice9Ex wined3d_mutex_lock(); for (i = 0; i < device->implicit_swapchain_count; ++i) { - if (FAILED(hr = wined3d_swapchain_present(device->implicit_swapchains[i]->wined3d_swapchain, - src_rect, dst_rect, dst_window_override, 0, flags))) + swapchain = device->implicit_swapchains[i]; + if (FAILED(hr = wined3d_swapchain_present(swapchain->wined3d_swapchain, + src_rect, dst_rect, dst_window_override, swapchain->swap_interval, flags))) { wined3d_mutex_unlock(); return hr; @@ -3727,21 +3762,31 @@ static HRESULT WINAPI d3d9_device_CheckResourceResidency(IDirect3DDevice9Ex *ifa static HRESULT WINAPI d3d9_device_SetMaximumFrameLatency(IDirect3DDevice9Ex *iface, UINT max_latency) { + struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); + TRACE("iface %p, max_latency %u.\n", iface, max_latency); - if (max_latency) - FIXME("Ignoring max_latency %u.\n", max_latency); + if (max_latency > 30) + return D3DERR_INVALIDCALL; + + wined3d_mutex_lock(); + wined3d_device_set_max_frame_latency(device->wined3d_device, max_latency); + wined3d_mutex_unlock(); return S_OK; } static HRESULT WINAPI d3d9_device_GetMaximumFrameLatency(IDirect3DDevice9Ex *iface, UINT *max_latency) { - FIXME("iface %p, max_latency %p stub!\n", iface, max_latency); + struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); - *max_latency = 2; + TRACE("iface %p, max_latency %p.\n", iface, max_latency); - return E_NOTIMPL; + wined3d_mutex_lock(); + *max_latency = wined3d_device_get_max_frame_latency(device->wined3d_device); + wined3d_mutex_unlock(); + + return S_OK; } static HRESULT WINAPI d3d9_device_CheckDeviceState(IDirect3DDevice9Ex *iface, HWND dst_window) @@ -4050,40 +4095,40 @@ static void CDECL device_parent_activate(struct wined3d_device_parent *device_pa InterlockedCompareExchange(&device->device_state, D3D9_DEVICE_STATE_NOT_RESET, D3D9_DEVICE_STATE_LOST); } -static HRESULT CDECL device_parent_surface_created(struct wined3d_device_parent *device_parent, - struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx, +static HRESULT CDECL device_parent_texture_sub_resource_created(struct wined3d_device_parent *device_parent, + enum wined3d_resource_type type, struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx, void **parent, const struct wined3d_parent_ops **parent_ops) { - struct d3d9_surface *d3d_surface; + TRACE("device_parent %p, type %#x, wined3d_texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n", + device_parent, type, wined3d_texture, sub_resource_idx, parent, parent_ops); - TRACE("device_parent %p, wined3d_texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n", - device_parent, wined3d_texture, sub_resource_idx, parent, parent_ops); - - if (!(d3d_surface = heap_alloc_zero(sizeof(*d3d_surface)))) - return E_OUTOFMEMORY; + if (type == WINED3D_RTYPE_TEXTURE_2D) + { + struct d3d9_surface *d3d_surface; - surface_init(d3d_surface, wined3d_texture, sub_resource_idx, parent_ops); - *parent = d3d_surface; - TRACE("Created surface %p.\n", d3d_surface); + if (!(d3d_surface = heap_alloc_zero(sizeof(*d3d_surface)))) + return E_OUTOFMEMORY; - return D3D_OK; -} - -static HRESULT CDECL device_parent_volume_created(struct wined3d_device_parent *device_parent, - struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx, - void **parent, const struct wined3d_parent_ops **parent_ops) -{ - struct d3d9_volume *d3d_volume; + surface_init(d3d_surface, wined3d_texture, sub_resource_idx, parent_ops); + *parent = d3d_surface; + TRACE("Created surface %p.\n", d3d_surface); + } + else if (type == WINED3D_RTYPE_TEXTURE_3D) + { + struct d3d9_volume *d3d_volume; - TRACE("device_parent %p, texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n", - device_parent, wined3d_texture, sub_resource_idx, parent, parent_ops); + if (!(d3d_volume = heap_alloc_zero(sizeof(*d3d_volume)))) + return E_OUTOFMEMORY; - if (!(d3d_volume = heap_alloc_zero(sizeof(*d3d_volume)))) - return E_OUTOFMEMORY; - - volume_init(d3d_volume, wined3d_texture, sub_resource_idx, parent_ops); - *parent = d3d_volume; - TRACE("Created volume %p.\n", d3d_volume); + volume_init(d3d_volume, wined3d_texture, sub_resource_idx, parent_ops); + *parent = d3d_volume; + TRACE("Created volume %p.\n", d3d_volume); + } + else + { + ERR("Unhandled resource type %#x.\n", type); + return E_FAIL; + } return D3D_OK; } @@ -4128,8 +4173,7 @@ static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent TRACE("device_parent %p, desc %p, swapchain %p\n", device_parent, desc, swapchain); - hr = d3d9_swapchain_create(device, desc, &d3d_swapchain); - if (FAILED(hr)) + if (FAILED(hr = d3d9_swapchain_create(device, desc, WINED3D_SWAP_INTERVAL_DEFAULT, &d3d_swapchain))) { WARN("Failed to create swapchain, hr %#x.\n", hr); *swapchain = NULL; @@ -4148,8 +4192,7 @@ static const struct wined3d_device_parent_ops d3d9_wined3d_device_parent_ops = device_parent_wined3d_device_created, device_parent_mode_changed, device_parent_activate, - device_parent_surface_created, - device_parent_volume_created, + device_parent_texture_sub_resource_created, device_parent_create_swapchain_texture, device_parent_create_swapchain, }; @@ -4272,10 +4315,16 @@ HRESULT device_init(struct d3d9_device *device, struct d3d9 *parent, struct wine wined3d_mutex_unlock(); return E_OUTOFMEMORY; } + for (i = 0; i < device->implicit_swapchain_count; ++i) + { + device->implicit_swapchains[i]->swap_interval + = wined3dswapinterval_from_d3d(parameters[i].PresentationInterval); + } for (i = 0; i < count; ++i) { - present_parameters_from_wined3d_swapchain_desc(¶meters[i], &swapchain_desc[i]); + present_parameters_from_wined3d_swapchain_desc(¶meters[i], + &swapchain_desc[i], parameters[i].PresentationInterval); } wined3d_mutex_unlock(); diff --git a/dll/directx/wine/d3d9/directx.c b/dll/directx/wine/d3d9/directx.c index 644766c2e9..98f4a99c49 100644 --- a/dll/directx/wine/d3d9/directx.c +++ b/dll/directx/wine/d3d9/directx.c @@ -254,6 +254,12 @@ static HRESULT WINAPI d3d9_CheckDeviceFormat(IDirect3D9Ex *iface, UINT adapter, TRACE("iface %p, adapter %u, device_type %#x, adapter_format %#x, usage %#x, resource_type %#x, format %#x.\n", iface, adapter, device_type, adapter_format, usage, resource_type, format); + if (!adapter_format) + { + WARN("Invalid adapter format.\n"); + return D3DERR_INVALIDCALL; + } + usage = usage & (WINED3DUSAGE_MASK | WINED3DUSAGE_QUERY_MASK); switch (resource_type) { @@ -579,7 +585,7 @@ BOOL d3d9_init(struct d3d9 *d3d9, BOOL extended) DWORD flags = WINED3D_PRESENT_CONVERSION | WINED3D_HANDLE_RESTORE | WINED3D_PIXEL_CENTER_INTEGER | WINED3D_SRGB_READ_WRITE_CONTROL | WINED3D_LEGACY_UNBOUND_RESOURCE_COLOR | WINED3D_NO_PRIMITIVE_RESTART | WINED3D_LEGACY_CUBEMAP_FILTERING - | WINED3D_NORMALIZED_DEPTH_BIAS | WINED3D_LIMIT_VIEWPORT; + | WINED3D_NORMALIZED_DEPTH_BIAS; if (!extended) flags |= WINED3D_VIDMEM_ACCOUNTING; diff --git a/dll/directx/wine/d3d9/swapchain.c b/dll/directx/wine/d3d9/swapchain.c index dbb3f45b91..d303f3f956 100644 --- a/dll/directx/wine/d3d9/swapchain.c +++ b/dll/directx/wine/d3d9/swapchain.c @@ -25,6 +25,27 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d9); +static DWORD d3dpresentationinterval_from_wined3dswapinterval(enum wined3d_swap_interval interval) +{ + switch (interval) + { + case WINED3D_SWAP_INTERVAL_IMMEDIATE: + return D3DPRESENT_INTERVAL_IMMEDIATE; + case WINED3D_SWAP_INTERVAL_ONE: + return D3DPRESENT_INTERVAL_ONE; + case WINED3D_SWAP_INTERVAL_TWO: + return D3DPRESENT_INTERVAL_TWO; + case WINED3D_SWAP_INTERVAL_THREE: + return D3DPRESENT_INTERVAL_THREE; + case WINED3D_SWAP_INTERVAL_FOUR: + return D3DPRESENT_INTERVAL_FOUR; + default: + ERR("Invalid swap interval %#x.\n", interval); + case WINED3D_SWAP_INTERVAL_DEFAULT: + return D3DPRESENT_INTERVAL_DEFAULT; + } +} + static inline struct d3d9_swapchain *impl_from_IDirect3DSwapChain9Ex(IDirect3DSwapChain9Ex *iface) { return CONTAINING_RECORD(iface, struct d3d9_swapchain, IDirect3DSwapChain9Ex_iface); @@ -137,7 +158,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_swapchain_Present(IDirect3DSwapChai wined3d_mutex_lock(); hr = wined3d_swapchain_present(swapchain->wined3d_swapchain, - src_rect, dst_rect, dst_window_override, 0, flags); + src_rect, dst_rect, dst_window_override, swapchain->swap_interval, flags); wined3d_mutex_unlock(); return hr; @@ -251,13 +272,15 @@ static HRESULT WINAPI d3d9_swapchain_GetPresentParameters(IDirect3DSwapChain9Ex { struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9Ex(iface); struct wined3d_swapchain_desc desc; + DWORD presentation_interval; TRACE("iface %p, parameters %p.\n", iface, parameters); wined3d_mutex_lock(); wined3d_swapchain_get_desc(swapchain->wined3d_swapchain, &desc); + presentation_interval = d3dpresentationinterval_from_wined3dswapinterval(swapchain->swap_interval); wined3d_mutex_unlock(); - present_parameters_from_wined3d_swapchain_desc(parameters, &desc); + present_parameters_from_wined3d_swapchain_desc(parameters, &desc, presentation_interval); return D3D_OK; } @@ -344,12 +367,13 @@ static const struct wined3d_parent_ops d3d9_swapchain_wined3d_parent_ops = }; static HRESULT swapchain_init(struct d3d9_swapchain *swapchain, struct d3d9_device *device, - struct wined3d_swapchain_desc *desc) + struct wined3d_swapchain_desc *desc, unsigned int swap_interval) { HRESULT hr; swapchain->refcount = 1; swapchain->IDirect3DSwapChain9Ex_iface.lpVtbl = &d3d9_swapchain_vtbl; + swapchain->swap_interval = swap_interval; wined3d_mutex_lock(); hr = wined3d_swapchain_create(device->wined3d_device, desc, swapchain, @@ -369,7 +393,7 @@ static HRESULT swapchain_init(struct d3d9_swapchain *swapchain, struct d3d9_devi } HRESULT d3d9_swapchain_create(struct d3d9_device *device, struct wined3d_swapchain_desc *desc, - struct d3d9_swapchain **swapchain) + unsigned int swap_interval, struct d3d9_swapchain **swapchain) { struct d3d9_swapchain *object; HRESULT hr; @@ -377,7 +401,7 @@ HRESULT d3d9_swapchain_create(struct d3d9_device *device, struct wined3d_swapcha if (!(object = heap_alloc_zero(sizeof(*object)))) return E_OUTOFMEMORY; - if (FAILED(hr = swapchain_init(object, device, desc))) + if (FAILED(hr = swapchain_init(object, device, desc, swap_interval))) { WARN("Failed to initialize swapchain, hr %#x.\n", hr); heap_free(object); diff --git a/dll/directx/wine/d3d9/texture.c b/dll/directx/wine/d3d9/texture.c index c97fa6b021..7b74ac5b9e 100644 --- a/dll/directx/wine/d3d9/texture.c +++ b/dll/directx/wine/d3d9/texture.c @@ -1339,9 +1339,22 @@ HRESULT texture_init(struct d3d9_texture *texture, struct d3d9_device *device, WARN("D3DUSAGE_AUTOGENMIPMAP texture with %u levels, returning D3DERR_INVALIDCALL.\n", levels); return D3DERR_INVALIDCALL; } - flags |= WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS; + wined3d_mutex_lock(); + hr = wined3d_check_device_format(device->d3d_parent->wined3d, 0, WINED3D_DEVICE_TYPE_HAL, WINED3DFMT_B8G8R8A8_UNORM, + WINED3DUSAGE_TEXTURE | WINED3DUSAGE_QUERY_GENMIPMAP, WINED3D_RTYPE_TEXTURE_2D, wined3dformat_from_d3dformat(format)); + wined3d_mutex_unlock(); + if (hr == D3D_OK) + { + flags |= WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS; + levels = 0; + } + else + { + WARN("D3DUSAGE_AUTOGENMIPMAP not supported on D3DFORMAT %#x, creating a texture " + "with a single level.\n", format); + levels = 1; + } texture->autogen_filter_type = D3DTEXF_LINEAR; - levels = 0; } else { diff --git a/dll/directx/wine/ddraw/ddraw.c b/dll/directx/wine/ddraw/ddraw.c index e5205c0d00..6b5ccece46 100644 --- a/dll/directx/wine/ddraw/ddraw.c +++ b/dll/directx/wine/ddraw/ddraw.c @@ -633,8 +633,9 @@ static HRESULT ddraw_create_swapchain(struct ddraw *ddraw, HWND window, BOOL win swapchain_desc.backbuffer_width = mode.width; swapchain_desc.backbuffer_height = mode.height; swapchain_desc.backbuffer_format = mode.format_id; - swapchain_desc.backbuffer_usage = WINED3DUSAGE_RENDERTARGET; - swapchain_desc.swap_effect = WINED3D_SWAP_EFFECT_COPY; + swapchain_desc.backbuffer_usage = 0; + swapchain_desc.backbuffer_count = 1; + swapchain_desc.swap_effect = WINED3D_SWAP_EFFECT_DISCARD; swapchain_desc.device_window = window; swapchain_desc.windowed = windowed; swapchain_desc.flags = WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH; @@ -2099,7 +2100,7 @@ static HRESULT WINAPI ddraw7_FlipToGDISurface(IDirectDraw7 *iface) ddraw->flags |= DDRAW_GDI_FLIP; if (ddraw->primary) - ddraw_surface_update_frontbuffer(ddraw->primary, NULL, FALSE); + ddraw_surface_update_frontbuffer(ddraw->primary, NULL, FALSE, 0); return DD_OK; } @@ -4909,18 +4910,19 @@ void ddraw_update_lost_surfaces(struct ddraw *ddraw) ddraw->device_state = DDRAW_DEVICE_STATE_OK; } -static HRESULT CDECL device_parent_surface_created(struct wined3d_device_parent *device_parent, - struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx, +static HRESULT CDECL device_parent_texture_sub_resource_created(struct wined3d_device_parent *device_parent, + enum wined3d_resource_type type, struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx, void **parent, const struct wined3d_parent_ops **parent_ops) { struct ddraw *ddraw = ddraw_from_device_parent(device_parent); struct ddraw_surface *ddraw_surface; - TRACE("device_parent %p, wined3d_texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n", - device_parent, wined3d_texture, sub_resource_idx, parent, parent_ops); + TRACE("device_parent %p, type %#x, wined3d_texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n", + device_parent, type, wined3d_texture, sub_resource_idx, parent, parent_ops); /* We have a swapchain or wined3d internal texture. */ - if (!wined3d_texture_get_parent(wined3d_texture) || wined3d_texture_get_parent(wined3d_texture) == ddraw) + if (type != WINED3D_RTYPE_TEXTURE_2D || !wined3d_texture_get_parent(wined3d_texture) + || wined3d_texture_get_parent(wined3d_texture) == ddraw) { *parent = NULL; *parent_ops = &ddraw_null_wined3d_parent_ops; @@ -4945,19 +4947,6 @@ static HRESULT CDECL device_parent_surface_created(struct wined3d_device_parent return DD_OK; } -static HRESULT CDECL device_parent_volume_created(struct wined3d_device_parent *device_parent, - struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx, - void **parent, const struct wined3d_parent_ops **parent_ops) -{ - TRACE("device_parent %p, texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n", - device_parent, wined3d_texture, sub_resource_idx, parent, parent_ops); - - *parent = NULL; - *parent_ops = &ddraw_null_wined3d_parent_ops; - - return DD_OK; -} - static void STDMETHODCALLTYPE ddraw_frontbuffer_destroyed(void *parent) { struct ddraw *ddraw = parent; @@ -4974,25 +4963,26 @@ static HRESULT CDECL device_parent_create_swapchain_texture(struct wined3d_devic struct wined3d_texture **texture) { struct ddraw *ddraw = ddraw_from_device_parent(device_parent); + const struct wined3d_parent_ops *parent_ops; HRESULT hr; TRACE("device_parent %p, container_parent %p, desc %p, texture flags %#x, texture %p.\n", device_parent, container_parent, desc, texture_flags, texture); - if (ddraw->wined3d_frontbuffer) - { - ERR("Frontbuffer already created.\n"); - return E_FAIL; - } + if (!ddraw->wined3d_frontbuffer) + parent_ops = &ddraw_frontbuffer_parent_ops; + else + parent_ops = &ddraw_null_wined3d_parent_ops; if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, desc, 1, 1, - texture_flags | WINED3D_TEXTURE_CREATE_MAPPABLE, NULL, ddraw, &ddraw_frontbuffer_parent_ops, texture))) + texture_flags | WINED3D_TEXTURE_CREATE_MAPPABLE, NULL, ddraw, parent_ops, texture))) { WARN("Failed to create texture, hr %#x.\n", hr); return hr; } - ddraw->wined3d_frontbuffer = *texture; + if (!ddraw->wined3d_frontbuffer) + ddraw->wined3d_frontbuffer = *texture; return hr; } @@ -5023,8 +5013,7 @@ static const struct wined3d_device_parent_ops ddraw_wined3d_device_parent_ops = device_parent_wined3d_device_created, device_parent_mode_changed, device_parent_activate, - device_parent_surface_created, - device_parent_volume_created, + device_parent_texture_sub_resource_created, device_parent_create_swapchain_texture, device_parent_create_swapchain, }; diff --git a/dll/directx/wine/ddraw/ddraw_private.h b/dll/directx/wine/ddraw/ddraw_private.h index 1454e8012a..9757008e92 100644 --- a/dll/directx/wine/ddraw/ddraw_private.h +++ b/dll/directx/wine/ddraw/ddraw_private.h @@ -59,14 +59,15 @@ struct FvfToDecl #define DDRAW_NO3D 0x00000008 #define DDRAW_SCL_DDRAW1 0x00000010 #define DDRAW_SCL_RECURSIVE 0x00000020 -#define DDRAW_GDI_FLIP 0x00000040 +#define DDRAW_SWAPPED 0x00000040 +#define DDRAW_GDI_FLIP 0x00000080 #define DDRAW_STRIDE_ALIGNMENT 8 #define DDRAW_WINED3D_FLAGS (WINED3D_LEGACY_DEPTH_BIAS | WINED3D_VIDMEM_ACCOUNTING \ | WINED3D_RESTORE_MODE_ON_ACTIVATE | WINED3D_FOCUS_MESSAGES | WINED3D_PIXEL_CENTER_INTEGER \ | WINED3D_LEGACY_UNBOUND_RESOURCE_COLOR | WINED3D_NO_PRIMITIVE_RESTART \ - | WINED3D_LEGACY_CUBEMAP_FILTERING | WINED3D_LIMIT_VIEWPORT) + | WINED3D_LEGACY_CUBEMAP_FILTERING) enum ddraw_device_state { @@ -220,7 +221,7 @@ void ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw, struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx, const struct wined3d_parent_ops **parent_ops) DECLSPEC_HIDDEN; HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, - const RECT *rect, BOOL read) DECLSPEC_HIDDEN; + const RECT *rect, BOOL read, unsigned int swap_interval) DECLSPEC_HIDDEN; static inline struct ddraw_surface *impl_from_IDirect3DTexture(IDirect3DTexture *iface) { diff --git a/dll/directx/wine/ddraw/device.c b/dll/directx/wine/ddraw/device.c index 24dbd3be50..799b2bcaa0 100644 --- a/dll/directx/wine/ddraw/device.c +++ b/dll/directx/wine/ddraw/device.c @@ -5296,25 +5296,12 @@ static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWO return hr; } -/***************************************************************************** - * IDirect3DDevice7::SetViewport - * - * Sets the current viewport. - * - * Version 7 only, but IDirect3DViewport uses this call for older - * versions - * - * Params: - * Data: The new viewport to set - * - * Returns: - * D3D_OK on success - * DDERR_INVALIDPARAMS if Data is NULL - * - *****************************************************************************/ static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport) { struct d3d_device *device = impl_from_IDirect3DDevice7(iface); + struct wined3d_sub_resource_desc rt_desc; + struct wined3d_rendertarget_view *rtv; + struct ddraw_surface *surface; struct wined3d_viewport vp; TRACE("iface %p, viewport %p.\n", iface, viewport); @@ -5322,6 +5309,23 @@ static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *vi if (!viewport) return DDERR_INVALIDPARAMS; + wined3d_mutex_lock(); + if (!(rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0))) + { + wined3d_mutex_unlock(); + return DDERR_INVALIDCAPS; + } + surface = wined3d_rendertarget_view_get_sub_resource_parent(rtv); + wined3d_texture_get_sub_resource_desc(surface->wined3d_texture, surface->sub_resource_idx, &rt_desc); + + if (viewport->dwX > rt_desc.width || viewport->dwWidth > rt_desc.width - viewport->dwX + || viewport->dwY > rt_desc.height || viewport->dwHeight > rt_desc.height - viewport->dwY) + { + WARN("Invalid viewport, returning E_INVALIDARG.\n"); + wined3d_mutex_unlock(); + return E_INVALIDARG; + } + vp.x = viewport->dwX; vp.y = viewport->dwY; vp.width = viewport->dwWidth; @@ -5329,8 +5333,7 @@ static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *vi vp.min_z = viewport->dvMinZ; vp.max_z = viewport->dvMaxZ; - wined3d_mutex_lock(); - wined3d_device_set_viewport(device->wined3d_device, &vp); + wined3d_device_set_viewports(device->wined3d_device, 1, &vp); wined3d_mutex_unlock(); return D3D_OK; @@ -5353,21 +5356,6 @@ static HRESULT WINAPI d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *ifac return hr; } -/***************************************************************************** - * IDirect3DDevice::GetViewport - * - * Returns the current viewport - * - * Version 7 - * - * Params: - * Data: D3D7Viewport structure to write the viewport information to - * - * Returns: - * D3D_OK on success - * DDERR_INVALIDPARAMS if Data is NULL - * - *****************************************************************************/ static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport) { struct d3d_device *device = impl_from_IDirect3DDevice7(iface); @@ -5379,7 +5367,7 @@ static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *vi return DDERR_INVALIDPARAMS; wined3d_mutex_lock(); - wined3d_device_get_viewport(device->wined3d_device, &wined3d_viewport); + wined3d_device_get_viewports(device->wined3d_device, NULL, &wined3d_viewport); wined3d_mutex_unlock(); viewport->dwX = wined3d_viewport.x; diff --git a/dll/directx/wine/ddraw/executebuffer.c b/dll/directx/wine/ddraw/executebuffer.c index 17bea2764c..e2c4fc11ab 100644 --- a/dll/directx/wine/ddraw/executebuffer.c +++ b/dll/directx/wine/ddraw/executebuffer.c @@ -348,7 +348,7 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer, wined3d_device_copy_sub_resource_region(device->wined3d_device, wined3d_buffer_get_resource(buffer->dst_vertex_buffer), 0, ci->wDest * sizeof(D3DTLVERTEX), 0, 0, - wined3d_buffer_get_resource(buffer->src_vertex_buffer), 0, &box); + wined3d_buffer_get_resource(buffer->src_vertex_buffer), 0, &box, 0); break; default: @@ -610,9 +610,16 @@ static HRESULT WINAPI d3d_execute_buffer_SetExecuteData(IDirect3DExecuteBuffer * struct wined3d_map_desc map_desc; struct wined3d_box box = {0}; HRESULT hr; + DWORD buf_size = buffer->desc.dwBufferSize, copy_size; TRACE("iface %p, data %p.\n", iface, data); + if (data->dwSize != sizeof(*data)) + { + WARN("data->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", data->dwSize); + return DDERR_INVALIDPARAMS; + } + /* Skip past previous vertex data. */ buffer->src_vertex_pos += buffer->data.dwVertexCount; @@ -659,7 +666,7 @@ static HRESULT WINAPI d3d_execute_buffer_SetExecuteData(IDirect3DExecuteBuffer * buffer->src_vertex_pos = 0; } - if (data->dwVertexCount) + if (data->dwVertexCount && (!buf_size || data->dwVertexOffset < buf_size)) { box.left = buffer->src_vertex_pos * sizeof(D3DVERTEX); box.right = box.left + data->dwVertexCount * sizeof(D3DVERTEX); @@ -667,8 +674,11 @@ static HRESULT WINAPI d3d_execute_buffer_SetExecuteData(IDirect3DExecuteBuffer * 0, &map_desc, &box, WINED3D_MAP_WRITE))) return hr; - memcpy(map_desc.data, ((BYTE *)buffer->desc.lpData) + data->dwVertexOffset, - data->dwVertexCount * sizeof(D3DVERTEX)); + copy_size = data->dwVertexCount * sizeof(D3DVERTEX); + if (buf_size) + copy_size = min(copy_size, buf_size - data->dwVertexOffset); + + memcpy(map_desc.data, ((BYTE *)buffer->desc.lpData) + data->dwVertexOffset, copy_size); wined3d_resource_unmap(wined3d_buffer_get_resource(buffer->src_vertex_buffer), 0); } @@ -696,12 +706,11 @@ static HRESULT WINAPI d3d_execute_buffer_SetExecuteData(IDirect3DExecuteBuffer * static HRESULT WINAPI d3d_execute_buffer_GetExecuteData(IDirect3DExecuteBuffer *iface, D3DEXECUTEDATA *data) { struct d3d_execute_buffer *buffer = impl_from_IDirect3DExecuteBuffer(iface); - DWORD dwSize; TRACE("iface %p, data %p.\n", iface, data); - dwSize = data->dwSize; - memcpy(data, &buffer->data, dwSize); + /* Tests show that dwSize is ignored. */ + memcpy(data, &buffer->data, sizeof(*data)); if (TRACE_ON(ddraw)) { diff --git a/dll/directx/wine/ddraw/palette.c b/dll/directx/wine/ddraw/palette.c index 5148832cab..87aec96443 100644 --- a/dll/directx/wine/ddraw/palette.c +++ b/dll/directx/wine/ddraw/palette.c @@ -176,7 +176,7 @@ static HRESULT WINAPI ddraw_palette_SetEntries(IDirectDrawPalette *iface, hr = wined3d_palette_set_entries(palette->wined3d_palette, flags, start, count, entries); if (SUCCEEDED(hr) && palette->flags & DDPCAPS_PRIMARYSURFACE) - ddraw_surface_update_frontbuffer(palette->ddraw->primary, NULL, FALSE); + ddraw_surface_update_frontbuffer(palette->ddraw->primary, NULL, FALSE, 0); wined3d_mutex_unlock(); diff --git a/dll/directx/wine/ddraw/surface.c b/dll/directx/wine/ddraw/surface.c index 5eefc228e6..e188396eb3 100644 --- a/dll/directx/wine/ddraw/surface.c +++ b/dll/directx/wine/ddraw/surface.c @@ -40,15 +40,22 @@ static inline struct ddraw_surface *impl_from_IDirectDrawGammaControl(IDirectDra * applications from drawing to the screen while we've locked the frontbuffer. * We'd like to do this in wined3d instead, but for that to work wined3d needs * to support windowless rendering first. */ -HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, const RECT *rect, BOOL read) +HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, + const RECT *rect, BOOL read, unsigned int swap_interval) { - struct ddraw *ddraw = surface->ddraw; + struct wined3d_texture *dst_texture; HDC surface_dc, screen_dc; int x, y, w, h; HRESULT hr; BOOL ret; RECT r; + if (surface->ddraw->flags & DDRAW_SWAPPED && !read) + { + surface->ddraw->flags &= ~DDRAW_SWAPPED; + rect = NULL; + } + if (!rect) { SetRect(&r, 0, 0, surface->surface_desc.dwWidth, surface->surface_desc.dwHeight); @@ -63,15 +70,25 @@ HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, const RE if (w <= 0 || h <= 0) return DD_OK; - if (ddraw->swapchain_window && !(ddraw->flags & DDRAW_GDI_FLIP)) + if (surface->ddraw->swapchain_window && !(surface->ddraw->flags & DDRAW_GDI_FLIP)) { /* Nothing to do, we control the frontbuffer, or at least the parts we * care about. */ if (read) return DD_OK; - return wined3d_texture_blt(ddraw->wined3d_frontbuffer, 0, rect, - surface->wined3d_texture, surface->sub_resource_idx, rect, 0, NULL, WINED3D_TEXF_POINT); + if (swap_interval) + dst_texture = wined3d_swapchain_get_back_buffer(surface->ddraw->wined3d_swapchain, 0); + else + dst_texture = surface->ddraw->wined3d_frontbuffer; + + if (SUCCEEDED(hr = wined3d_texture_blt(dst_texture, 0, rect, surface->wined3d_texture, + surface->sub_resource_idx, rect, 0, NULL, WINED3D_TEXF_POINT)) && swap_interval) + { + hr = wined3d_swapchain_present(surface->ddraw->wined3d_swapchain, rect, rect, NULL, swap_interval, 0); + surface->ddraw->flags |= DDRAW_SWAPPED; + } + return hr; } if (FAILED(hr = wined3d_texture_get_dc(surface->wined3d_texture, surface->sub_resource_idx, &surface_dc))) @@ -474,7 +491,7 @@ static HRESULT ddraw_surface_set_palette(struct ddraw_surface *surface, IDirectD palette_impl->flags |= DDPCAPS_PRIMARYSURFACE; wined3d_swapchain_set_palette(surface->ddraw->wined3d_swapchain, palette_impl ? palette_impl->wined3d_palette : NULL); - ddraw_surface_update_frontbuffer(surface, NULL, FALSE); + ddraw_surface_update_frontbuffer(surface, NULL, FALSE, 0); } if (palette_impl) IDirectDrawPalette_AddRef(&palette_impl->IDirectDrawPalette_iface); @@ -990,7 +1007,7 @@ static HRESULT surface_lock(struct ddraw_surface *surface, } if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) - hr = ddraw_surface_update_frontbuffer(surface, rect, TRUE); + hr = ddraw_surface_update_frontbuffer(surface, rect, TRUE, 0); if (SUCCEEDED(hr)) hr = wined3d_resource_map(wined3d_texture_get_resource(surface->wined3d_texture), surface->sub_resource_idx, &map_desc, rect ? &box : NULL, @@ -1179,7 +1196,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Unlock(IDirectDrawSurface wined3d_mutex_lock(); hr = wined3d_resource_unmap(wined3d_texture_get_resource(surface->wined3d_texture), surface->sub_resource_idx); if (SUCCEEDED(hr) && surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) - hr = ddraw_surface_update_frontbuffer(surface, &surface->ddraw->primary_lock, FALSE); + hr = ddraw_surface_update_frontbuffer(surface, &surface->ddraw->primary_lock, FALSE, 0); wined3d_mutex_unlock(); return hr; @@ -1224,6 +1241,24 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Unlock(IDirectDrawSurface return ddraw_surface7_Unlock(&surface->IDirectDrawSurface7_iface, NULL); } +static unsigned int ddraw_swap_interval_from_flags(DWORD flags) +{ + if (flags & DDFLIP_NOVSYNC) + return 0; + + switch (flags & (DDFLIP_INTERVAL2 | DDFLIP_INTERVAL3 | DDFLIP_INTERVAL4)) + { + case DDFLIP_INTERVAL2: + return 2; + case DDFLIP_INTERVAL3: + return 3; + case DDFLIP_INTERVAL4: + return 4; + default: + return 1; + } +} + static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Flip(IDirectDrawSurface7 *iface, IDirectDrawSurface7 *src, DWORD flags) { @@ -1337,7 +1372,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Flip(IDirectDrawSurface7 wined3d_resource_set_parent(wined3d_texture_get_resource(texture), ddraw_texture); src_impl->wined3d_texture = texture; - if (flags) + if (flags & ~(DDFLIP_NOVSYNC | DDFLIP_INTERVAL2 | DDFLIP_INTERVAL3 | DDFLIP_INTERVAL4)) { static UINT once; if (!once++) @@ -1347,7 +1382,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Flip(IDirectDrawSurface7 } if (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) - hr = ddraw_surface_update_frontbuffer(dst_impl, NULL, FALSE); + hr = ddraw_surface_update_frontbuffer(dst_impl, NULL, FALSE, ddraw_swap_interval_from_flags(flags)); else hr = DD_OK; @@ -1488,11 +1523,11 @@ static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface *dst_surface, cons if (!dst_surface->clipper) { if (src_surface && src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) - hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect, TRUE); + hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect, TRUE, 0); if (SUCCEEDED(hr)) hr = ddraw_surface_blt(dst_surface, &dst_rect, src_surface, &src_rect, flags, fill_colour, fx, filter); if (SUCCEEDED(hr) && (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) - hr = ddraw_surface_update_frontbuffer(dst_surface, &dst_rect, FALSE); + hr = ddraw_surface_update_frontbuffer(dst_surface, &dst_rect, FALSE, 0); return hr; } @@ -1535,7 +1570,7 @@ static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface *dst_surface, cons if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) { - if (FAILED(hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect_clipped, TRUE))) + if (FAILED(hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect_clipped, TRUE, 0))) break; } } @@ -1546,7 +1581,7 @@ static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface *dst_surface, cons if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) { - if (FAILED(hr = ddraw_surface_update_frontbuffer(dst_surface, &clip_rect[i], FALSE))) + if (FAILED(hr = ddraw_surface_update_frontbuffer(dst_surface, &clip_rect[i], FALSE, 0))) break; } } @@ -2219,7 +2254,7 @@ static HRESULT WINAPI ddraw_surface7_GetDC(IDirectDrawSurface7 *iface, HDC *dc) if (surface->dc) hr = DDERR_DCALREADYCREATED; else if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) - hr = ddraw_surface_update_frontbuffer(surface, NULL, TRUE); + hr = ddraw_surface_update_frontbuffer(surface, NULL, TRUE, 0); if (SUCCEEDED(hr)) hr = wined3d_texture_get_dc(surface->wined3d_texture, surface->sub_resource_idx, dc); @@ -2321,7 +2356,7 @@ static HRESULT WINAPI ddraw_surface7_ReleaseDC(IDirectDrawSurface7 *iface, HDC h { surface->dc = NULL; if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) - hr = ddraw_surface_update_frontbuffer(surface, NULL, FALSE); + hr = ddraw_surface_update_frontbuffer(surface, NULL, FALSE, 0); } wined3d_mutex_unlock(); @@ -4289,12 +4324,12 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_BltFast(IDirectDrawSurfac } if (src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) - hr = ddraw_surface_update_frontbuffer(src_impl, src_rect, TRUE); + hr = ddraw_surface_update_frontbuffer(src_impl, src_rect, TRUE, 0); if (SUCCEEDED(hr)) hr = wined3d_texture_blt(dst_impl->wined3d_texture, dst_impl->sub_resource_idx, &dst_rect, src_impl->wined3d_texture, src_impl->sub_resource_idx, src_rect, flags, NULL, WINED3D_TEXF_POINT); if (SUCCEEDED(hr) && (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) - hr = ddraw_surface_update_frontbuffer(dst_impl, &dst_rect, FALSE); + hr = ddraw_surface_update_frontbuffer(dst_impl, &dst_rect, FALSE, 0); wined3d_mutex_unlock(); switch(hr) diff --git a/dll/directx/wine/ddraw/utils.c b/dll/directx/wine/ddraw/utils.c index 65f24dc13f..b0a028d4a5 100644 --- a/dll/directx/wine/ddraw/utils.c +++ b/dll/directx/wine/ddraw/utils.c @@ -570,7 +570,7 @@ unsigned int wined3dmapflags_from_ddrawmapflags(unsigned int flags) unsigned int wined3d_flags; wined3d_flags = flags & handled; - if (!(flags & (DDLOCK_NOOVERWRITE | DDLOCK_DISCARDCONTENTS))) + if (!(flags & (DDLOCK_NOOVERWRITE | DDLOCK_DISCARDCONTENTS | DDLOCK_WRITEONLY))) wined3d_flags |= WINED3D_MAP_READ; if (!(flags & DDLOCK_READONLY)) wined3d_flags |= WINED3D_MAP_WRITE; @@ -578,7 +578,7 @@ unsigned int wined3dmapflags_from_ddrawmapflags(unsigned int flags) wined3d_flags |= WINED3D_MAP_READ | WINED3D_MAP_WRITE; if (flags & DDLOCK_NODIRTYUPDATE) wined3d_flags |= WINED3D_MAP_NO_DIRTY_UPDATE; - flags &= ~(handled | DDLOCK_WAIT | DDLOCK_READONLY | DDLOCK_NODIRTYUPDATE); + flags &= ~(handled | DDLOCK_WAIT | DDLOCK_READONLY | DDLOCK_WRITEONLY | DDLOCK_NODIRTYUPDATE); if (flags) FIXME("Unhandled flags %#x.\n", flags); diff --git a/dll/directx/wine/ddraw/viewport.c b/dll/directx/wine/ddraw/viewport.c index 6ef3226c4d..f2caf20858 100644 --- a/dll/directx/wine/ddraw/viewport.c +++ b/dll/directx/wine/ddraw/viewport.c @@ -249,109 +249,118 @@ static HRESULT WINAPI d3d_viewport_Initialize(IDirect3DViewport3 *iface, IDirect return DDERR_ALREADYINITIALIZED; } -/***************************************************************************** - * IDirect3DViewport3::GetViewport - * - * Returns the viewport data assigned to this viewport interface - * - * Params: - * Data: Address to store the data - * - * Returns: - * D3D_OK on success - * DDERR_INVALIDPARAMS if Data is NULL - * - *****************************************************************************/ -static HRESULT WINAPI d3d_viewport_GetViewport(IDirect3DViewport3 *iface, D3DVIEWPORT *lpData) +static HRESULT WINAPI d3d_viewport_GetViewport(IDirect3DViewport3 *iface, D3DVIEWPORT *vp) { - struct d3d_viewport *This = impl_from_IDirect3DViewport3(iface); - DWORD dwSize; + struct d3d_viewport *viewport = impl_from_IDirect3DViewport3(iface); + DWORD size; + + TRACE("iface %p, vp %p.\n", iface, vp); - TRACE("iface %p, data %p.\n", iface, lpData); + if (!vp) + return DDERR_INVALIDPARAMS; wined3d_mutex_lock(); - dwSize = lpData->dwSize; - if (!This->use_vp2) - memcpy(lpData, &(This->viewports.vp1), dwSize); - else { + size = vp->dwSize; + if (!viewport->use_vp2) + { + memcpy(vp, &viewport->viewports.vp1, size); + } + else + { D3DVIEWPORT vp1; + vp1.dwSize = sizeof(vp1); - vp1.dwX = This->viewports.vp2.dwX; - vp1.dwY = This->viewports.vp2.dwY; - vp1.dwWidth = This->viewports.vp2.dwWidth; - vp1.dwHeight = This->viewports.vp2.dwHeight; + vp1.dwX = viewport->viewports.vp2.dwX; + vp1.dwY = viewport->viewports.vp2.dwY; + vp1.dwWidth = viewport->viewports.vp2.dwWidth; + vp1.dwHeight = viewport->viewports.vp2.dwHeight; vp1.dvMaxX = 0.0; vp1.dvMaxY = 0.0; vp1.dvScaleX = 0.0; vp1.dvScaleY = 0.0; - vp1.dvMinZ = This->viewports.vp2.dvMinZ; - vp1.dvMaxZ = This->viewports.vp2.dvMaxZ; - memcpy(lpData, &vp1, dwSize); + vp1.dvMinZ = viewport->viewports.vp2.dvMinZ; + vp1.dvMaxZ = viewport->viewports.vp2.dvMaxZ; + memcpy(vp, &vp1, size); } if (TRACE_ON(ddraw)) { TRACE(" returning D3DVIEWPORT :\n"); - _dump_D3DVIEWPORT(lpData); + _dump_D3DVIEWPORT(vp); } wined3d_mutex_unlock(); - return DD_OK; + return D3D_OK; } -/***************************************************************************** - * IDirect3DViewport3::SetViewport - * - * Sets the viewport information for this interface - * - * Params: - * lpData: Viewport to set - * - * Returns: - * D3D_OK on success - * DDERR_INVALIDPARAMS if Data is NULL - * - *****************************************************************************/ -static HRESULT WINAPI d3d_viewport_SetViewport(IDirect3DViewport3 *iface, D3DVIEWPORT *lpData) +static HRESULT WINAPI d3d_viewport_SetViewport(IDirect3DViewport3 *iface, D3DVIEWPORT *vp) { - struct d3d_viewport *This = impl_from_IDirect3DViewport3(iface); + struct d3d_viewport *viewport = impl_from_IDirect3DViewport3(iface); + struct d3d_device *device = viewport->active_device; + struct wined3d_sub_resource_desc rt_desc; + struct wined3d_rendertarget_view *rtv; IDirect3DViewport3 *current_viewport; + struct ddraw_surface *surface; - TRACE("iface %p, data %p.\n", iface, lpData); + TRACE("iface %p, vp %p.\n", iface, vp); + + if (!vp) + return DDERR_INVALIDPARAMS; if (TRACE_ON(ddraw)) { TRACE(" getting D3DVIEWPORT :\n"); - _dump_D3DVIEWPORT(lpData); + _dump_D3DVIEWPORT(vp); } - wined3d_mutex_lock(); - - This->use_vp2 = 0; - memset(&(This->viewports.vp1), 0, sizeof(This->viewports.vp1)); - memcpy(&(This->viewports.vp1), lpData, lpData->dwSize); + if (!device) + { + WARN("Viewport not bound to a device, returning D3DERR_VIEWPORTHASNODEVICE.\n"); + return D3DERR_VIEWPORTHASNODEVICE; + } - /* Tests on two games show that these values are never used properly so override - them with proper ones :-) - */ - This->viewports.vp1.dvMinZ = 0.0; - This->viewports.vp1.dvMaxZ = 1.0; + wined3d_mutex_lock(); - if (This->active_device) + if (device->version > 1) { - IDirect3DDevice3 *d3d_device3 = &This->active_device->IDirect3DDevice3_iface; - if (SUCCEEDED(IDirect3DDevice3_GetCurrentViewport(d3d_device3, ¤t_viewport))) + if (!(rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0))) + { + wined3d_mutex_unlock(); + return DDERR_INVALIDCAPS; + } + surface = wined3d_rendertarget_view_get_sub_resource_parent(rtv); + wined3d_texture_get_sub_resource_desc(surface->wined3d_texture, surface->sub_resource_idx, &rt_desc); + + if (vp->dwX > rt_desc.width || vp->dwWidth > rt_desc.width - vp->dwX + || vp->dwY > rt_desc.height || vp->dwHeight > rt_desc.height - vp->dwY) { - if (current_viewport == iface) viewport_activate(This, FALSE); - IDirect3DViewport3_Release(current_viewport); + WARN("Invalid viewport, returning DDERR_INVALIDPARAMS.\n"); + wined3d_mutex_unlock(); + return DDERR_INVALIDPARAMS; } } + viewport->use_vp2 = 0; + memset(&viewport->viewports.vp1, 0, sizeof(viewport->viewports.vp1)); + memcpy(&viewport->viewports.vp1, vp, vp->dwSize); + + /* Empirical testing on a couple of d3d1 games showed that these values + * should be ignored. */ + viewport->viewports.vp1.dvMinZ = 0.0; + viewport->viewports.vp1.dvMaxZ = 1.0; + + if (SUCCEEDED(IDirect3DDevice3_GetCurrentViewport(&device->IDirect3DDevice3_iface, ¤t_viewport))) + { + if (current_viewport == iface) + viewport_activate(viewport, FALSE); + IDirect3DViewport3_Release(current_viewport); + } + wined3d_mutex_unlock(); - return DD_OK; + return D3D_OK; } /***************************************************************************** @@ -882,53 +891,44 @@ static HRESULT WINAPI d3d_viewport_NextLight(IDirect3DViewport3 *iface, * IDirect3DViewport2 Methods. *****************************************************************************/ -/***************************************************************************** - * IDirect3DViewport3::GetViewport2 - * - * Returns the currently set viewport in a D3DVIEWPORT2 structure. - * Similar to IDirect3DViewport3::GetViewport - * - * Params: - * lpData: Pointer to the structure to fill - * - * Returns: - * D3D_OK on success - * DDERR_INVALIDPARAMS if the viewport was set with - * IDirect3DViewport3::SetViewport - * DDERR_INVALIDPARAMS if Data is NULL - * - *****************************************************************************/ -static HRESULT WINAPI d3d_viewport_GetViewport2(IDirect3DViewport3 *iface, D3DVIEWPORT2 *lpData) +static HRESULT WINAPI d3d_viewport_GetViewport2(IDirect3DViewport3 *iface, D3DVIEWPORT2 *vp) { - struct d3d_viewport *This = impl_from_IDirect3DViewport3(iface); - DWORD dwSize; + struct d3d_viewport *viewport = impl_from_IDirect3DViewport3(iface); + DWORD size; - TRACE("iface %p, data %p.\n", iface, lpData); + TRACE("iface %p, vp %p.\n", iface, vp); + + if (!vp) + return DDERR_INVALIDPARAMS; wined3d_mutex_lock(); - dwSize = lpData->dwSize; - if (This->use_vp2) - memcpy(lpData, &(This->viewports.vp2), dwSize); - else { + size = vp->dwSize; + if (viewport->use_vp2) + { + memcpy(vp, &viewport->viewports.vp2, size); + } + else + { D3DVIEWPORT2 vp2; + vp2.dwSize = sizeof(vp2); - vp2.dwX = This->viewports.vp1.dwX; - vp2.dwY = This->viewports.vp1.dwY; - vp2.dwWidth = This->viewports.vp1.dwWidth; - vp2.dwHeight = This->viewports.vp1.dwHeight; + vp2.dwX = viewport->viewports.vp1.dwX; + vp2.dwY = viewport->viewports.vp1.dwY; + vp2.dwWidth = viewport->viewports.vp1.dwWidth; + vp2.dwHeight = viewport->viewports.vp1.dwHeight; vp2.dvClipX = 0.0; vp2.dvClipY = 0.0; vp2.dvClipWidth = 0.0; vp2.dvClipHeight = 0.0; - vp2.dvMinZ = This->viewports.vp1.dvMinZ; - vp2.dvMaxZ = This->viewports.vp1.dvMaxZ; - memcpy(lpData, &vp2, dwSize); + vp2.dvMinZ = viewport->viewports.vp1.dvMinZ; + vp2.dvMaxZ = viewport->viewports.vp1.dvMaxZ; + memcpy(vp, &vp2, size); } if (TRACE_ON(ddraw)) { TRACE(" returning D3DVIEWPORT2 :\n"); - _dump_D3DVIEWPORT2(lpData); + _dump_D3DVIEWPORT2(vp); } wined3d_mutex_unlock(); @@ -936,47 +936,64 @@ static HRESULT WINAPI d3d_viewport_GetViewport2(IDirect3DViewport3 *iface, D3DVI return D3D_OK; } -/***************************************************************************** - * IDirect3DViewport3::SetViewport2 - * - * Sets the viewport from a D3DVIEWPORT2 structure - * - * Params: - * lpData: Viewport to set - * - * Returns: - * D3D_OK on success - * - *****************************************************************************/ -static HRESULT WINAPI d3d_viewport_SetViewport2(IDirect3DViewport3 *iface, D3DVIEWPORT2 *lpData) +static HRESULT WINAPI d3d_viewport_SetViewport2(IDirect3DViewport3 *iface, D3DVIEWPORT2 *vp) { - struct d3d_viewport *This = impl_from_IDirect3DViewport3(iface); + struct d3d_viewport *viewport = impl_from_IDirect3DViewport3(iface); + struct d3d_device *device = viewport->active_device; + struct wined3d_sub_resource_desc rt_desc; + struct wined3d_rendertarget_view *rtv; IDirect3DViewport3 *current_viewport; + struct ddraw_surface *surface; + + TRACE("iface %p, vp %p.\n", iface, vp); - TRACE("iface %p, data %p.\n", iface, lpData); + if (!vp) + return DDERR_INVALIDPARAMS; if (TRACE_ON(ddraw)) { TRACE(" getting D3DVIEWPORT2 :\n"); - _dump_D3DVIEWPORT2(lpData); + _dump_D3DVIEWPORT2(vp); } - wined3d_mutex_lock(); + if (!device) + { + WARN("Viewport not bound to a device, returning D3DERR_VIEWPORTHASNODEVICE.\n"); + return D3DERR_VIEWPORTHASNODEVICE; + } - This->use_vp2 = 1; - memset(&(This->viewports.vp2), 0, sizeof(This->viewports.vp2)); - memcpy(&(This->viewports.vp2), lpData, lpData->dwSize); + wined3d_mutex_lock(); - if (This->active_device) + if (device->version > 1) { - IDirect3DDevice3 *d3d_device3 = &This->active_device->IDirect3DDevice3_iface; - if (SUCCEEDED(IDirect3DDevice3_GetCurrentViewport(d3d_device3, ¤t_viewport))) + if (!(rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0))) + { + wined3d_mutex_unlock(); + return DDERR_INVALIDCAPS; + } + surface = wined3d_rendertarget_view_get_sub_resource_parent(rtv); + wined3d_texture_get_sub_resource_desc(surface->wined3d_texture, surface->sub_resource_idx, &rt_desc); + + if (vp->dwX > rt_desc.width || vp->dwWidth > rt_desc.width - vp->dwX + || vp->dwY > rt_desc.height || vp->dwHeight > rt_desc.height - vp->dwY) { - if (current_viewport == iface) viewport_activate(This, FALSE); - IDirect3DViewport3_Release(current_viewport); + WARN("Invalid viewport, returning DDERR_INVALIDPARAMS.\n"); + wined3d_mutex_unlock(); + return DDERR_INVALIDPARAMS; } } + viewport->use_vp2 = 1; + memset(&viewport->viewports.vp2, 0, sizeof(viewport->viewports.vp2)); + memcpy(&viewport->viewports.vp2, vp, vp->dwSize); + + if (SUCCEEDED(IDirect3DDevice3_GetCurrentViewport(&device->IDirect3DDevice3_iface, ¤t_viewport))) + { + if (current_viewport == iface) + viewport_activate(viewport, FALSE); + IDirect3DViewport3_Release(current_viewport); + } + wined3d_mutex_unlock(); return D3D_OK; diff --git a/dll/directx/wine/wined3d/arb_program_shader.c b/dll/directx/wine/wined3d/arb_program_shader.c index f86c167b60..4fbb3a59ec 100644 --- a/dll/directx/wine/wined3d/arb_program_shader.c +++ b/dll/directx/wine/wined3d/arb_program_shader.c @@ -611,7 +611,7 @@ static void shader_arb_vs_local_constants(const struct arb_vs_compiled_shader *g unsigned char i; /* Upload the position fixup */ - shader_get_position_fixup(context, state, position_fixup); + shader_get_position_fixup(context, state, 1, position_fixup); GL_EXTCALL(glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, gl_shader->pos_fixup, position_fixup)); if (!gl_shader->num_int_consts) return; @@ -1061,7 +1061,7 @@ static void shader_arb_get_register_name(const struct wined3d_shader_instruction /* This is better than nothing for now */ sprintf(register_name, "fragment.texcoord[%s + %u]", rel_reg, reg->idx[0].offset); } - else if(ctx->cur_ps_args->super.vp_mode != vertexshader) + else if(ctx->cur_ps_args->super.vp_mode != WINED3D_VP_MODE_SHADER) { /* This is problematic because we'd have to consult the ctx->ps_input strings * for where to find the varying. Some may be "0.0", others can be texcoords or @@ -1416,9 +1416,6 @@ static void shader_hw_sample(const struct wined3d_shader_instruction *ins, DWORD struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; const char *mod; BOOL pshader = shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type); - const struct wined3d_shader *shader; - const struct wined3d_device *device; - const struct wined3d_gl_info *gl_info; const char *tex_dst = dst_str; struct color_fixup_masks masks; @@ -1432,12 +1429,8 @@ static void shader_hw_sample(const struct wined3d_shader_instruction *ins, DWORD break; case WINED3D_SHADER_RESOURCE_TEXTURE_2D: - shader = ins->ctx->shader; - device = shader->device; - gl_info = &device->adapter->gl_info; - if (pshader && priv->cur_ps_args->super.np2_fixup & (1u << sampler_idx) - && gl_info->supported[ARB_TEXTURE_RECTANGLE]) + && ins->ctx->gl_info->supported[ARB_TEXTURE_RECTANGLE]) tex_type = "RECT"; else tex_type = "2D"; @@ -3422,73 +3415,68 @@ static void init_ps_input(const struct wined3d_shader *shader, const char *semantic_name; DWORD semantic_idx; - switch(args->super.vp_mode) - { - case pretransformed: - case fixedfunction: - /* The pixelshader has to collect the varyings on its own. In any case properly load - * color0 and color1. In the case of pretransformed vertices also load texcoords. Set - * other attribs to 0.0. - * - * For fixedfunction this behavior is correct, according to the tests. For pretransformed - * we'd either need a replacement shader that can load other attribs like BINORMAL, or - * load the texcoord attrib pointers to match the pixel shader signature - */ - for (i = 0; i < shader->input_signature.element_count; ++i) - { - input = &shader->input_signature.elements[i]; - if (!(semantic_name = input->semantic_name)) - continue; - semantic_idx = input->semantic_idx; + if (args->super.vp_mode == WINED3D_VP_MODE_SHADER) + { + /* That one is easy. The vertex shaders provide v0-v7 in + * fragment.texcoord and v8 and v9 in fragment.color. */ + for (i = 0; i < 8; ++i) + { + priv->ps_input[i] = texcoords[i]; + } + priv->ps_input[8] = "fragment.color.primary"; + priv->ps_input[9] = "fragment.color.secondary"; + return; + } - if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_COLOR)) - { - if (!semantic_idx) - priv->ps_input[input->register_idx] = "fragment.color.primary"; - else if (semantic_idx == 1) - priv->ps_input[input->register_idx] = "fragment.color.secondary"; - else - priv->ps_input[input->register_idx] = "0.0"; - } - else if (args->super.vp_mode == fixedfunction) - { - priv->ps_input[input->register_idx] = "0.0"; - } - else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_TEXCOORD)) - { - if (semantic_idx < 8) - priv->ps_input[input->register_idx] = texcoords[semantic_idx]; - else - priv->ps_input[input->register_idx] = "0.0"; - } - else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_FOG)) - { - if (!semantic_idx) - priv->ps_input[input->register_idx] = "fragment.fogcoord"; - else - priv->ps_input[input->register_idx] = "0.0"; - } - else - { - priv->ps_input[input->register_idx] = "0.0"; - } + /* The fragment shader has to collect the varyings on its own. In any case + * properly load color0 and color1. In the case of pre-transformed + * vertices also load texture coordinates. Set other attributes to 0.0. + * + * For fixed-function this behavior is correct, according to the tests. + * For pre-transformed we'd either need a replacement shader that can load + * other attributes like BINORMAL, or load the texture coordinate + * attribute pointers to match the fragment shader signature. */ + for (i = 0; i < shader->input_signature.element_count; ++i) + { + input = &shader->input_signature.elements[i]; + if (!(semantic_name = input->semantic_name)) + continue; + semantic_idx = input->semantic_idx; - TRACE("v%u, semantic %s%u is %s\n", input->register_idx, - semantic_name, semantic_idx, priv->ps_input[input->register_idx]); - } - break; + if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_COLOR)) + { + if (!semantic_idx) + priv->ps_input[input->register_idx] = "fragment.color.primary"; + else if (semantic_idx == 1) + priv->ps_input[input->register_idx] = "fragment.color.secondary"; + else + priv->ps_input[input->register_idx] = "0.0"; + } + else if (args->super.vp_mode == WINED3D_VP_MODE_FF) + { + priv->ps_input[input->register_idx] = "0.0"; + } + else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_TEXCOORD)) + { + if (semantic_idx < 8) + priv->ps_input[input->register_idx] = texcoords[semantic_idx]; + else + priv->ps_input[input->register_idx] = "0.0"; + } + else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_FOG)) + { + if (!semantic_idx) + priv->ps_input[input->register_idx] = "fragment.fogcoord"; + else + priv->ps_input[input->register_idx] = "0.0"; + } + else + { + priv->ps_input[input->register_idx] = "0.0"; + } - case vertexshader: - /* That one is easy. The vertex shaders provide v0-v7 in fragment.texcoord and v8 and v9 in - * fragment.color - */ - for(i = 0; i < 8; i++) - { - priv->ps_input[i] = texcoords[i]; - } - priv->ps_input[8] = "fragment.color.primary"; - priv->ps_input[9] = "fragment.color.secondary"; - break; + TRACE("v%u, semantic %s%u is %s\n", input->register_idx, + semantic_name, semantic_idx, priv->ps_input[input->register_idx]); } } @@ -6084,17 +6072,19 @@ static const char *get_argreg(struct wined3d_string_buffer *buffer, DWORD argnum } static void gen_ffp_instr(struct wined3d_string_buffer *buffer, unsigned int stage, BOOL color, - BOOL alpha, DWORD dst, DWORD op, DWORD dw_arg0, DWORD dw_arg1, DWORD dw_arg2) + BOOL alpha, BOOL tmp_dst, DWORD op, DWORD dw_arg0, DWORD dw_arg1, DWORD dw_arg2) { const char *dstmask, *dstreg, *arg0, *arg1, *arg2; unsigned int mul = 1; - if(color && alpha) dstmask = ""; - else if(color) dstmask = ".xyz"; - else dstmask = ".w"; + if (color && alpha) + dstmask = ""; + else if (color) + dstmask = ".xyz"; + else + dstmask = ".w"; - if(dst == tempreg) dstreg = "tempreg"; - else dstreg = "ret"; + dstreg = tmp_dst ? "tempreg" : "ret"; arg0 = get_argreg(buffer, 0, stage, dw_arg0); arg1 = get_argreg(buffer, 1, stage, dw_arg1); @@ -6273,7 +6263,7 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, con if (arg0 == WINED3DTA_TEXTURE || arg1 == WINED3DTA_TEXTURE || arg2 == WINED3DTA_TEXTURE) tex_read |= 1u << stage; - if (settings->op[stage].dst == tempreg) + if (settings->op[stage].tmp_dst) tempreg_used = TRUE; if (arg0 == WINED3DTA_TEMP || arg1 == WINED3DTA_TEMP || arg2 == WINED3DTA_TEMP) tempreg_used = TRUE; @@ -6391,12 +6381,17 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, con textype = arbfp_texture_target(settings->op[stage].tex_type); - if(settings->op[stage].projected == proj_none) { + if (settings->op[stage].projected == WINED3D_PROJECTION_NONE) + { instr = "TEX"; - } else if(settings->op[stage].projected == proj_count4 || - settings->op[stage].projected == proj_count3) { + } + else if (settings->op[stage].projected == WINED3D_PROJECTION_COUNT4 + || settings->op[stage].projected == WINED3D_PROJECTION_COUNT3) + { instr = "TXP"; - } else { + } + else + { FIXME("Unexpected projection mode %d\n", settings->op[stage].projected); instr = "TXP"; } @@ -6410,18 +6405,27 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, con shader_addline(&buffer, "SWZ arg1, bumpmat%u, y, w, 0, 0;\n", stage - 1); shader_addline(&buffer, "DP3 ret.y, arg1, tex%u;\n", stage - 1); - /* with projective textures, texbem only divides the static texture coord, not the displacement, - * so multiply the displacement with the dividing parameter before passing it to TXP - */ - if (settings->op[stage].projected != proj_none) { - if(settings->op[stage].projected == proj_count4) { + /* With projective textures, texbem only divides the static + * texture coordinate, not the displacement, so multiply the + * displacement with the dividing parameter before passing it to + * TXP. */ + if (settings->op[stage].projected != WINED3D_PROJECTION_NONE) + { + if (settings->op[stage].projected == WINED3D_PROJECTION_COUNT4) + { shader_addline(&buffer, "MOV ret.w, fragment.texcoord[%u].w;\n", stage); - shader_addline(&buffer, "MUL ret.xyz, ret, fragment.texcoord[%u].w, fragment.texcoord[%u];\n", stage, stage); - } else { + shader_addline(&buffer, "MUL ret.xyz, ret, fragment.texcoord[%u].w, fragment.texcoord[%u];\n", + stage, stage); + } + else + { shader_addline(&buffer, "MOV ret.w, fragment.texcoord[%u].z;\n", stage); - shader_addline(&buffer, "MAD ret.xyz, ret, fragment.texcoord[%u].z, fragment.texcoord[%u];\n", stage, stage); + shader_addline(&buffer, "MAD ret.xyz, ret, fragment.texcoord[%u].z, fragment.texcoord[%u];\n", + stage, stage); } - } else { + } + else + { shader_addline(&buffer, "ADD ret, ret, fragment.texcoord[%u];\n", stage); } @@ -6433,12 +6437,16 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, con stage - 1, stage - 1, stage - 1); shader_addline(&buffer, "MUL tex%u, tex%u, ret.x;\n", stage, stage); } - } else if(settings->op[stage].projected == proj_count3) { + } + else if (settings->op[stage].projected == WINED3D_PROJECTION_COUNT3) + { shader_addline(&buffer, "MOV ret, fragment.texcoord[%u];\n", stage); shader_addline(&buffer, "MOV ret.w, ret.z;\n"); shader_addline(&buffer, "%s tex%u, ret, texture[%u], %s;\n", instr, stage, stage, textype); - } else { + } + else + { shader_addline(&buffer, "%s tex%u, fragment.texcoord[%u], texture[%u], %s;\n", instr, stage, stage, stage, textype); } @@ -6487,23 +6495,23 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, con if (settings->op[stage].aop == WINED3D_TOP_DISABLE) { - gen_ffp_instr(&buffer, stage, TRUE, FALSE, settings->op[stage].dst, + gen_ffp_instr(&buffer, stage, TRUE, FALSE, settings->op[stage].tmp_dst, settings->op[stage].cop, settings->op[stage].carg0, settings->op[stage].carg1, settings->op[stage].carg2); } else if (op_equal) { - gen_ffp_instr(&buffer, stage, TRUE, TRUE, settings->op[stage].dst, + gen_ffp_instr(&buffer, stage, TRUE, TRUE, settings->op[stage].tmp_dst, settings->op[stage].cop, settings->op[stage].carg0, settings->op[stage].carg1, settings->op[stage].carg2); } else if (settings->op[stage].cop != WINED3D_TOP_BUMPENVMAP && settings->op[stage].cop != WINED3D_TOP_BUMPENVMAP_LUMINANCE) { - gen_ffp_instr(&buffer, stage, TRUE, FALSE, settings->op[stage].dst, + gen_ffp_instr(&buffer, stage, TRUE, FALSE, settings->op[stage].tmp_dst, settings->op[stage].cop, settings->op[stage].carg0, settings->op[stage].carg1, settings->op[stage].carg2); - gen_ffp_instr(&buffer, stage, FALSE, TRUE, settings->op[stage].dst, + gen_ffp_instr(&buffer, stage, FALSE, TRUE, settings->op[stage].tmp_dst, settings->op[stage].aop, settings->op[stage].aarg0, settings->op[stage].aarg1, settings->op[stage].aarg2); } @@ -6928,8 +6936,8 @@ static void arbfp_blitter_destroy(struct wined3d_blitter *blitter, struct wined3 heap_free(arbfp_blitter); } -static BOOL gen_planar_yuv_read(struct wined3d_string_buffer *buffer, const struct arbfp_blit_type *type, - char *luminance) +static void gen_packed_yuv_read(struct wined3d_string_buffer *buffer, + const struct arbfp_blit_type *type, char *luminance) { char chroma; const char *tex, *texinstr = "TXP"; @@ -6977,13 +6985,12 @@ static BOOL gen_planar_yuv_read(struct wined3d_string_buffer *buffer, const stru shader_addline(buffer, "FLR texcrd.x, texcrd.x;\n"); shader_addline(buffer, "ADD texcrd.x, texcrd.x, coef.y;\n"); - /* Divide the x coordinate by 0.5 and get the fraction. This gives 0.25 and 0.75 for the - * even and odd pixels respectively - */ + /* Multiply the x coordinate by 0.5 and get the fraction. This gives 0.25 + * and 0.75 for the even and odd pixels respectively. */ shader_addline(buffer, "MUL texcrd2, texcrd, coef.y;\n"); shader_addline(buffer, "FRC texcrd2, texcrd2;\n"); - /* Sample Pixel 1 */ + /* Sample Pixel 1. */ shader_addline(buffer, "%s luminance, texcrd, texture[0], %s;\n", texinstr, tex); /* Put the value into either of the chroma values */ @@ -7012,12 +7019,10 @@ static BOOL gen_planar_yuv_read(struct wined3d_string_buffer *buffer, const stru /* This gives the correctly filtered luminance value */ shader_addline(buffer, "TEX luminance, fragment.texcoord[0], texture[0], %s;\n", tex); - - return TRUE; } -static BOOL gen_yv12_read(struct wined3d_string_buffer *buffer, const struct arbfp_blit_type *type, - char *luminance) +static void gen_yv12_read(struct wined3d_string_buffer *buffer, + const struct arbfp_blit_type *type, char *luminance) { const char *tex; static const float yv12_coef[] @@ -7079,7 +7084,6 @@ static BOOL gen_yv12_read(struct wined3d_string_buffer *buffer, const struct arb */ if (type->res_type == WINED3D_GL_RES_TYPE_TEX_2D) { - shader_addline(buffer, "RCP chroma.w, size.y;\n"); shader_addline(buffer, "MUL texcrd2.y, texcrd.y, size.y;\n"); @@ -7087,7 +7091,7 @@ static BOOL gen_yv12_read(struct wined3d_string_buffer *buffer, const struct arb shader_addline(buffer, "FLR texcrd2.y, texcrd2.y;\n"); shader_addline(buffer, "MAD texcrd.y, texcrd.y, yv12_coef.y, yv12_coef.x;\n"); - /* Read odd lines from the right side(add size * 0.5 to the x coordinate */ + /* Read odd lines from the right side (add size * 0.5 to the x coordinate). */ shader_addline(buffer, "ADD texcrd2.x, texcrd2.y, yv12_coef.y;\n"); /* To avoid 0.5 == 0.5 comparisons */ shader_addline(buffer, "FRC texcrd2.x, texcrd2.x;\n"); shader_addline(buffer, "SGE texcrd2.x, texcrd2.x, coef.y;\n"); @@ -7101,11 +7105,11 @@ static BOOL gen_yv12_read(struct wined3d_string_buffer *buffer, const struct arb } else { - /* Read from [size - size+size/4] */ + /* The y coordinate for V is in the range [size, size + size / 4). */ shader_addline(buffer, "FLR texcrd.y, texcrd.y;\n"); shader_addline(buffer, "MAD texcrd.y, texcrd.y, coef.w, size.y;\n"); - /* Read odd lines from the right side(add size * 0.5 to the x coordinate */ + /* Read odd lines from the right side (add size * 0.5 to the x coordinate). */ shader_addline(buffer, "ADD texcrd2.x, texcrd.y, yv12_coef.y;\n"); /* To avoid 0.5 == 0.5 comparisons */ shader_addline(buffer, "FRC texcrd2.x, texcrd2.x;\n"); shader_addline(buffer, "SGE texcrd2.x, texcrd2.x, coef.y;\n"); @@ -7161,12 +7165,10 @@ static BOOL gen_yv12_read(struct wined3d_string_buffer *buffer, const struct arb shader_addline(buffer, "TEX luminance, texcrd, texture[0], %s;\n", tex); } *luminance = 'a'; - - return TRUE; } -static BOOL gen_nv12_read(struct wined3d_string_buffer *buffer, const struct arbfp_blit_type *type, - char *luminance) +static void gen_nv12_read(struct wined3d_string_buffer *buffer, + const struct arbfp_blit_type *type, char *luminance) { const char *tex; static const float nv12_coef[] @@ -7242,7 +7244,7 @@ static BOOL gen_nv12_read(struct wined3d_string_buffer *buffer, const struct arb } else { - /* Read from [size - size+size/2] */ + /* The y coordinate for chroma is in the range [size, size + size / 2). */ shader_addline(buffer, "MAD texcrd.y, texcrd.y, coef.y, size.y;\n"); shader_addline(buffer, "FLR texcrd.x, texcrd.x;\n"); @@ -7297,8 +7299,6 @@ static BOOL gen_nv12_read(struct wined3d_string_buffer *buffer, const struct arb shader_addline(buffer, "TEX luminance, texcrd, texture[0], %s;\n", tex); } *luminance = 'a'; - - return TRUE; } /* Context activation is done by the caller. */ @@ -7464,27 +7464,15 @@ static GLuint gen_yuv_shader(const struct wined3d_gl_info *gl_info, const struct { case COMPLEX_FIXUP_UYVY: case COMPLEX_FIXUP_YUY2: - if (!gen_planar_yuv_read(&buffer, type, &luminance_component)) - { - string_buffer_free(&buffer); - return 0; - } + gen_packed_yuv_read(&buffer, type, &luminance_component); break; case COMPLEX_FIXUP_YV12: - if (!gen_yv12_read(&buffer, type, &luminance_component)) - { - string_buffer_free(&buffer); - return 0; - } + gen_yv12_read(&buffer, type, &luminance_component); break; case COMPLEX_FIXUP_NV12: - if (!gen_nv12_read(&buffer, type, &luminance_component)) - { - string_buffer_free(&buffer); - return 0; - } + gen_nv12_read(&buffer, type, &luminance_component); break; default: @@ -7710,7 +7698,7 @@ static BOOL arbfp_blit_supported(enum wined3d_blit_op blit_op, const struct wine enum complex_fixup src_fixup; BOOL decompress; - if (!context->gl_info->supported[ARB_FRAGMENT_PROGRAM]) + if (src_resource->type != WINED3D_RTYPE_TEXTURE_2D) return FALSE; if (blit_op == WINED3D_BLIT_OP_RAW_BLIT && dst_format->id == src_format->id) @@ -7795,59 +7783,105 @@ static BOOL arbfp_blit_supported(enum wined3d_blit_op blit_op, const struct wine } static DWORD arbfp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_op op, - struct wined3d_context *context, struct wined3d_surface *src_surface, DWORD src_location, - const RECT *src_rect, struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect, + struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, + DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture, + unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect, const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type filter) { - unsigned int src_sub_resource_idx = surface_get_sub_resource_idx(src_surface); - struct wined3d_texture *src_texture = src_surface->container; - struct wined3d_texture *dst_texture = dst_surface->container; struct wined3d_device *device = dst_texture->resource.device; + struct wined3d_texture *staging_texture = NULL; struct wined3d_arbfp_blitter *arbfp_blitter; struct wined3d_color_key alpha_test_key; struct wined3d_blitter *next; + unsigned int src_level; RECT s, d; + TRACE("blitter %p, op %#x, context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, src_rect %s, " + "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, colour_key %p, filter %s.\n", + blitter, op, context, src_texture, src_sub_resource_idx, wined3d_debug_location(src_location), + wine_dbgstr_rect(src_rect), dst_texture, dst_sub_resource_idx, wined3d_debug_location(dst_location), + wine_dbgstr_rect(dst_rect), color_key, debug_d3dtexturefiltertype(filter)); + if (!arbfp_blit_supported(op, context, &src_texture->resource, src_location, &dst_texture->resource, dst_location)) { - if ((next = blitter->next)) - return next->ops->blitter_blit(next, op, context, src_surface, src_location, - src_rect, dst_surface, dst_location, dst_rect, color_key, filter); + if (!(next = blitter->next)) + { + ERR("No blitter to handle blit op %#x.\n", op); + return dst_location; + } + + TRACE("Forwarding to blitter %p.\n", next); + return next->ops->blitter_blit(next, op, context, src_texture, src_sub_resource_idx, src_location, + src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, color_key, filter); } arbfp_blitter = CONTAINING_RECORD(blitter, struct wined3d_arbfp_blitter, blitter); - /* Now load the surface */ - if (wined3d_settings.offscreen_rendering_mode != ORM_FBO - && (surface_get_sub_resource(src_surface)->locations - & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_DRAWABLE)) - == WINED3D_LOCATION_DRAWABLE + if (!(src_texture->resource.access & WINED3D_RESOURCE_ACCESS_GPU)) + { + struct wined3d_resource_desc desc; + struct wined3d_box upload_box; + HRESULT hr; + + TRACE("Source texture is not GPU accessible, creating a staging texture.\n"); + + src_level = src_sub_resource_idx % src_texture->level_count; + desc.resource_type = WINED3D_RTYPE_TEXTURE_2D; + desc.format = src_texture->resource.format->id; + desc.multisample_type = src_texture->resource.multisample_type; + desc.multisample_quality = src_texture->resource.multisample_quality; + desc.usage = WINED3DUSAGE_PRIVATE; + desc.access = WINED3D_RESOURCE_ACCESS_GPU; + desc.width = wined3d_texture_get_level_width(src_texture, src_level); + desc.height = wined3d_texture_get_level_height(src_texture, src_level); + desc.depth = 1; + desc.size = 0; + + if (FAILED(hr = wined3d_texture_create(device, &desc, 1, 1, 0, + NULL, NULL, &wined3d_null_parent_ops, &staging_texture))) + { + ERR("Failed to create staging texture, hr %#x.\n", hr); + return dst_location; + } + + wined3d_box_set(&upload_box, 0, 0, desc.width, desc.height, 0, desc.depth); + wined3d_texture_upload_from_texture(staging_texture, 0, 0, 0, 0, + src_texture, src_sub_resource_idx, &upload_box); + + src_texture = staging_texture; + src_sub_resource_idx = 0; + } + else if (wined3d_settings.offscreen_rendering_mode != ORM_FBO + && (src_texture->sub_resources[src_sub_resource_idx].locations + & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_DRAWABLE)) == WINED3D_LOCATION_DRAWABLE && !wined3d_resource_is_offscreen(&src_texture->resource)) { - unsigned int src_level = src_sub_resource_idx % src_texture->level_count; /* Without FBO blits transferring from the drawable to the texture is * expensive, because we have to flip the data in sysmem. Since we can * flip in the blitter, we don't actually need that flip anyway. So we * use the surface's texture as scratch texture, and flip the source * rectangle instead. */ - surface_load_fb_texture(src_surface, FALSE, context); + texture2d_load_fb_texture(src_texture, src_sub_resource_idx, FALSE, context); s = *src_rect; + src_level = src_sub_resource_idx % src_texture->level_count; s.top = wined3d_texture_get_level_height(src_texture, src_level) - s.top; s.bottom = wined3d_texture_get_level_height(src_texture, src_level) - s.bottom; src_rect = &s; } else + { wined3d_texture_load(src_texture, context, FALSE); + } - context_apply_blit_state(context, device); + context_apply_ffp_blit_state(context, device); if (dst_location == WINED3D_LOCATION_DRAWABLE) { d = *dst_rect; - surface_translate_drawable_coords(dst_surface, context->win_handle, &d); + wined3d_texture_translate_drawable_coords(dst_texture, context->win_handle, &d); dst_rect = &d; } @@ -7857,15 +7891,16 @@ static DWORD arbfp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bl if (dst_location == WINED3D_LOCATION_DRAWABLE) { - TRACE("Destination surface %p is onscreen.\n", dst_surface); + TRACE("Destination texture %p is onscreen.\n", dst_texture); buffer = wined3d_texture_get_gl_buffer(dst_texture); } else { - TRACE("Destination surface %p is offscreen.\n", dst_surface); + TRACE("Destination texture %p is offscreen.\n", dst_texture); buffer = GL_COLOR_ATTACHMENT0; } - context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, dst_surface, NULL, dst_location); + context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, + &dst_texture->resource, dst_sub_resource_idx, NULL, 0, dst_location); context_set_draw_buffer(context, buffer); context_check_fbo_status(context, GL_DRAW_FRAMEBUFFER); context_invalidate_state(context, STATE_FRAMEBUFFER); @@ -7882,14 +7917,16 @@ static DWORD arbfp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bl arbfp_blit_set(arbfp_blitter, context, src_texture, src_sub_resource_idx, color_key); /* Draw a textured quad */ - draw_textured_quad(src_texture, src_sub_resource_idx, context, src_rect, dst_rect, filter); + context_draw_textured_quad(context, src_texture, src_sub_resource_idx, src_rect, dst_rect, filter); /* Leave the opengl state valid for blitting */ arbfp_blit_unset(context->gl_info); - if (wined3d_settings.strict_draw_ordering - || (dst_texture->swapchain && (dst_texture->swapchain->front_buffer == dst_texture))) - context->gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ + if (dst_texture->swapchain && (dst_texture->swapchain->front_buffer == dst_texture)) + context->gl_info->gl_ops.gl.p_glFlush(); + + if (staging_texture) + wined3d_texture_decref(staging_texture); return dst_location; } diff --git a/dll/directx/wine/wined3d/ati_fragment_shader.c b/dll/directx/wine/wined3d/ati_fragment_shader.c index 9d6837a2f2..9a1cae34cd 100644 --- a/dll/directx/wine/wined3d/ati_fragment_shader.c +++ b/dll/directx/wine/wined3d/ati_fragment_shader.c @@ -341,9 +341,8 @@ static GLuint find_tmpreg(const struct texture_stage_op op[MAX_TEXTURES]) lowest_read = i; } - if(lowest_write == -1 && op[i].dst == tempreg) { + if (lowest_write == -1 && op[i].tmp_dst) lowest_write = i; - } if(op[i].carg1 == WINED3DTA_TEXTURE || op[i].carg2 == WINED3DTA_TEXTURE || op[i].carg0 == WINED3DTA_TEXTURE || op[i].aarg1 == WINED3DTA_TEXTURE || op[i].aarg2 == WINED3DTA_TEXTURE || op[i].aarg0 == WINED3DTA_TEXTURE) { @@ -505,16 +504,13 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], TRACE("glSampleMapATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB, GL_SWIZZLE_STR_ATI)\n", stage, stage); - GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage, - GL_TEXTURE0_ARB + stage, - GL_SWIZZLE_STR_ATI)); - if(op[stage + 1].projected == proj_none) { + GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage, GL_TEXTURE0_ARB + stage, GL_SWIZZLE_STR_ATI)); + if (op[stage + 1].projected == WINED3D_PROJECTION_NONE) swizzle = GL_SWIZZLE_STR_ATI; - } else if(op[stage + 1].projected == proj_count4) { + else if (op[stage + 1].projected == WINED3D_PROJECTION_COUNT4) swizzle = GL_SWIZZLE_STQ_DQ_ATI; - } else { + else swizzle = GL_SWIZZLE_STR_DR_ATI; - } TRACE("glPassTexCoordATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB, %s)\n", stage + 1, stage + 1, debug_swizzle(swizzle)); GL_EXTCALL(glPassTexCoordATI(GL_REG_0_ATI + stage + 1, @@ -579,13 +575,12 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], if (op[stage].cop == WINED3D_TOP_DISABLE) break; - if(op[stage].projected == proj_none) { + if (op[stage].projected == WINED3D_PROJECTION_NONE) swizzle = GL_SWIZZLE_STR_ATI; - } else if(op[stage].projected == proj_count3) { + else if (op[stage].projected == WINED3D_PROJECTION_COUNT3) swizzle = GL_SWIZZLE_STR_DR_ATI; - } else { + else swizzle = GL_SWIZZLE_STQ_DQ_ATI; - } if (op_reads_texture(&op[stage])) { @@ -624,14 +619,18 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], break; } - if(op[stage].dst == tempreg) { - /* If we're writing to D3DTA_TEMP, but never reading from it we don't have to write there in the first place. - * skip the entire stage, this saves some GPU time - */ - if(tmparg == GL_NONE) continue; + if (op[stage].tmp_dst) + { + /* If we're writing to D3DTA_TEMP, but never reading from it we + * don't have to write there in the first place. Skip the entire + * stage, this saves some GPU time. */ + if (tmparg == GL_NONE) + continue; dstreg = tmparg; - } else { + } + else + { dstreg = GL_REG_0_ATI; } diff --git a/dll/directx/wine/wined3d/buffer.c b/dll/directx/wine/wined3d/buffer.c index cae7ef8788..9baf0556dd 100644 --- a/dll/directx/wine/wined3d/buffer.c +++ b/dll/directx/wine/wined3d/buffer.c @@ -615,10 +615,7 @@ static BOOL wined3d_buffer_prepare_location(struct wined3d_buffer *buffer, return TRUE; if (!wined3d_resource_allocate_sysmem(&buffer->resource)) - { - ERR("Failed to allocate system memory.\n"); return FALSE; - } return TRUE; case WINED3D_LOCATION_BUFFER: @@ -1183,8 +1180,6 @@ static void wined3d_buffer_unmap(struct wined3d_buffer *buffer) } GL_EXTCALL(glUnmapBuffer(buffer->buffer_type_hint)); - if (wined3d_settings.strict_draw_ordering) - gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ context_release(context); buffer_clear_dirty_areas(buffer); @@ -1380,6 +1375,9 @@ static HRESULT buffer_init(struct wined3d_buffer *buffer, struct wined3d_device buffer->bind_flags = bind_flags; buffer->locations = WINED3D_LOCATION_SYSMEM; + if (!wined3d_resource_allocate_sysmem(&buffer->resource)) + return E_OUTOFMEMORY; + TRACE("buffer %p, size %#x, usage %#x, format %s, memory @ %p.\n", buffer, buffer->resource.size, buffer->resource.usage, debug_d3dformat(buffer->resource.format->id), buffer->resource.heap_memory); @@ -1428,7 +1426,7 @@ static HRESULT buffer_init(struct wined3d_buffer *buffer, struct wined3d_device if (data) wined3d_device_update_sub_resource(device, &buffer->resource, - 0, NULL, data->data, data->row_pitch, data->slice_pitch); + 0, NULL, data->data, data->row_pitch, data->slice_pitch, 0); return WINED3D_OK; } diff --git a/dll/directx/wine/wined3d/context.c b/dll/directx/wine/wined3d/context.c index 8a8d952c3f..0ee5b65bc1 100644 --- a/dll/directx/wine/wined3d/context.c +++ b/dll/directx/wine/wined3d/context.c @@ -148,8 +148,8 @@ static void context_attach_gl_texture_fbo(struct wined3d_context *context, gl_info->fbo_ops.glFramebufferTexture(fbo_target, attachment, resource->object, resource->level); } - else if (resource->target == GL_TEXTURE_1D_ARRAY || resource->target == GL_TEXTURE_2D_ARRAY || - resource->target == GL_TEXTURE_3D) + else if (resource->target == GL_TEXTURE_1D_ARRAY || resource->target == GL_TEXTURE_2D_ARRAY + || resource->target == GL_TEXTURE_3D) { if (!gl_info->fbo_ops.glFramebufferTextureLayer) { @@ -164,7 +164,6 @@ static void context_attach_gl_texture_fbo(struct wined3d_context *context, { gl_info->fbo_ops.glFramebufferTexture1D(fbo_target, attachment, resource->target, resource->object, resource->level); - checkGLcall("glFramebufferTexture1D()"); } else { @@ -253,6 +252,8 @@ static void context_dump_fbo_attachment(const struct wined3d_gl_info *gl_info, G } texture_type[] = { + {GL_TEXTURE_1D, GL_TEXTURE_BINDING_1D, "1d", WINED3D_GL_EXT_NONE}, + {GL_TEXTURE_1D_ARRAY, GL_TEXTURE_BINDING_1D_ARRAY, "1d-array", EXT_TEXTURE_ARRAY}, {GL_TEXTURE_2D, GL_TEXTURE_BINDING_2D, "2d", WINED3D_GL_EXT_NONE}, {GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_BINDING_RECTANGLE_ARB, "rectangle", ARB_TEXTURE_RECTANGLE}, {GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BINDING_2D_ARRAY, "2d-array" , EXT_TEXTURE_ARRAY}, @@ -456,19 +457,15 @@ static inline void context_set_fbo_key_for_render_target(const struct wined3d_co } texture = wined3d_texture_from_resource(resource); - if (resource->type == WINED3D_RTYPE_TEXTURE_2D) + if (texture->current_renderbuffer) { - struct wined3d_surface *surface = texture->sub_resources[sub_resource_idx].u.surface; - - if (surface->current_renderbuffer) - { - key->objects[idx].object = surface->current_renderbuffer->id; - key->objects[idx].target = 0; - key->objects[idx].level = key->objects[idx].layer = 0; - key->rb_namespace |= 1 << idx; - return; - } + key->objects[idx].object = texture->current_renderbuffer->id; + key->objects[idx].target = 0; + key->objects[idx].level = key->objects[idx].layer = 0; + key->rb_namespace |= 1 << idx; + return; } + key->objects[idx].target = wined3d_texture_get_sub_resource_target(texture, sub_resource_idx); key->objects[idx].level = sub_resource_idx % texture->level_count; key->objects[idx].layer = sub_resource_idx / texture->level_count; @@ -615,10 +612,7 @@ static struct fbo_entry *context_find_fbo_entry(struct wined3d_context *context, } else if (depth_stencil->resource->type == WINED3D_RTYPE_TEXTURE_2D) { - struct wined3d_surface *surface; - - surface = ds_texture->sub_resources[depth_stencil->sub_resource_idx].u.surface; - surface_set_compatible_renderbuffer(surface, &render_targets[0]); + wined3d_texture_set_compatible_renderbuffer(ds_texture, ds_level, &render_targets[0]); } } @@ -761,8 +755,8 @@ static void context_apply_fbo_entry(struct wined3d_context *context, GLenum targ /* Context activation is done by the caller. */ static void context_apply_fbo_state(struct wined3d_context *context, GLenum target, - struct wined3d_rendertarget_info *render_targets, struct wined3d_surface *depth_stencil, - DWORD color_location, DWORD ds_location) + const struct wined3d_rendertarget_info *render_targets, + const struct wined3d_rendertarget_info *depth_stencil, DWORD color_location, DWORD ds_location) { struct fbo_entry *entry, *entry2; @@ -784,32 +778,35 @@ static void context_apply_fbo_state(struct wined3d_context *context, GLenum targ } else { - struct wined3d_rendertarget_info ds = {{0}}; - - if (depth_stencil) - { - ds.resource = &depth_stencil->container->resource; - ds.sub_resource_idx = surface_get_sub_resource_idx(depth_stencil); - ds.layer_count = 1; - } context->current_fbo = context_find_fbo_entry(context, target, - render_targets, &ds, color_location, ds_location); + render_targets, depth_stencil, color_location, ds_location); context_apply_fbo_entry(context, target, context->current_fbo); } } /* Context activation is done by the caller. */ void context_apply_fbo_state_blit(struct wined3d_context *context, GLenum target, - struct wined3d_surface *render_target, struct wined3d_surface *depth_stencil, DWORD location) + struct wined3d_resource *rt, unsigned int rt_sub_resource_idx, + struct wined3d_resource *ds, unsigned int ds_sub_resource_idx, DWORD location) { + struct wined3d_rendertarget_info ds_info = {{0}}; + memset(context->blit_targets, 0, sizeof(context->blit_targets)); - if (render_target) + if (rt) { - context->blit_targets[0].resource = &render_target->container->resource; - context->blit_targets[0].sub_resource_idx = surface_get_sub_resource_idx(render_target); + context->blit_targets[0].resource = rt; + context->blit_targets[0].sub_resource_idx = rt_sub_resource_idx; context->blit_targets[0].layer_count = 1; } - context_apply_fbo_state(context, target, context->blit_targets, depth_stencil, location, location); + + if (ds) + { + ds_info.resource = ds; + ds_info.sub_resource_idx = ds_sub_resource_idx; + ds_info.layer_count = 1; + } + + context_apply_fbo_state(context, target, context->blit_targets, &ds_info, location, location); } /* Context activation is done by the caller. */ @@ -1070,34 +1067,22 @@ static void context_queue_fbo_entry_destruction(struct wined3d_context *context, list_add_head(&context->fbo_destroy_list, &entry->entry); } -void context_resource_released(const struct wined3d_device *device, - struct wined3d_resource *resource, enum wined3d_resource_type type) +void context_resource_released(const struct wined3d_device *device, struct wined3d_resource *resource) { - struct wined3d_texture *texture; - UINT i; + unsigned int i; if (!device->d3d_initialized) return; - switch (type) + for (i = 0; i < device->context_count; ++i) { - case WINED3D_RTYPE_TEXTURE_2D: - case WINED3D_RTYPE_TEXTURE_3D: - texture = texture_from_resource(resource); - - for (i = 0; i < device->context_count; ++i) - { - struct wined3d_context *context = device->contexts[i]; - if (context->current_rt.texture == texture) - { - context->current_rt.texture = NULL; - context->current_rt.sub_resource_idx = 0; - } - } - break; + struct wined3d_context *context = device->contexts[i]; - default: - break; + if (&context->current_rt.texture->resource == resource) + { + context->current_rt.texture = NULL; + context->current_rt.sub_resource_idx = 0; + } } } @@ -1107,7 +1092,7 @@ void context_gl_resource_released(struct wined3d_device *device, context_enum_fbo_entries(device, name, rb_namespace, context_queue_fbo_entry_destruction); } -void context_surface_update(struct wined3d_context *context, const struct wined3d_surface *surface) +void context_texture_update(struct wined3d_context *context, const struct wined3d_texture *texture) { const struct wined3d_gl_info *gl_info = context->gl_info; struct fbo_entry *entry = context->current_fbo; @@ -1117,10 +1102,10 @@ void context_surface_update(struct wined3d_context *context, const struct wined3 for (i = 0; i < gl_info->limits.buffers + 1; ++i) { - if (surface->container->texture_rgb.name == entry->key.objects[i].object - || surface->container->texture_srgb.name == entry->key.objects[i].object) + if (texture->texture_rgb.name == entry->key.objects[i].object + || texture->texture_srgb.name == entry->key.objects[i].object) { - TRACE("Updated surface %p is bound as attachment %u to the current FBO.\n", surface, i); + TRACE("Updated texture %p is bound as attachment %u to the current FBO.\n", texture, i); context->rebind_fbo = TRUE; return; } @@ -1466,6 +1451,9 @@ static void context_destroy_gl_resources(struct wined3d_context *context) } } + if (context->blit_vbo) + GL_EXTCALL(glDeleteBuffers(1, &context->blit_vbo)); + checkGLcall("context cleanup"); } @@ -1603,14 +1591,12 @@ void context_release(struct wined3d_context *context) /* This is used when a context for render target A is active, but a separate context is * needed to access the WGL framebuffer for render target B. Re-acquire a context for rt * A to avoid breaking caller code. */ -void context_restore(struct wined3d_context *context, struct wined3d_surface *restore) +void context_restore(struct wined3d_context *context, struct wined3d_texture *texture, unsigned int sub_resource_idx) { - if (context->current_rt.texture != restore->container - || context->current_rt.sub_resource_idx != surface_get_sub_resource_idx(restore)) + if (context->current_rt.texture != texture || context->current_rt.sub_resource_idx != sub_resource_idx) { context_release(context); - context = context_acquire(restore->container->resource.device, - restore->container, surface_get_sub_resource_idx(restore)); + context = context_acquire(texture->resource.device, texture, sub_resource_idx); } context_release(context); @@ -1791,6 +1777,7 @@ void context_bind_dummy_textures(const struct wined3d_device *device, const stru gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D_ARRAY, textures->tex_1d_array); gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D_ARRAY, textures->tex_2d_array); } + if (gl_info->supported[ARB_TEXTURE_BUFFER_OBJECT]) gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_BUFFER, textures->tex_buffer); @@ -1866,8 +1853,6 @@ HGLRC context_create_wgl_attribs(const struct wined3d_gl_info *gl_info, HDC hdc, ctx_attribs[ctx_attrib_idx++] = gl_info->selected_gl_version >> 16; ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_MINOR_VERSION_ARB; ctx_attribs[ctx_attrib_idx++] = gl_info->selected_gl_version & 0xffff; - if (gl_info->selected_gl_version >= MAKEDWORD_VERSION(3, 2)) - ctx_flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; if (ctx_flags) { ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_FLAGS_ARB; @@ -1877,9 +1862,20 @@ HGLRC context_create_wgl_attribs(const struct wined3d_gl_info *gl_info, HDC hdc, if (!(ctx = gl_info->p_wglCreateContextAttribsARB(hdc, share_ctx, ctx_attribs))) { - if (ctx_flags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) + if (gl_info->selected_gl_version >= MAKEDWORD_VERSION(3, 2)) { - ctx_attribs[ctx_attrib_idx - 1] &= ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; + if (ctx_flags) + { + ctx_flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; + ctx_attribs[ctx_attrib_idx - 1] = ctx_flags; + } + else + { + ctx_flags = WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; + ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_FLAGS_ARB; + ctx_attribs[ctx_attrib_idx++] = ctx_flags; + ctx_attribs[ctx_attrib_idx] = 0; + } if (!(ctx = gl_info->p_wglCreateContextAttribsARB(hdc, share_ctx, ctx_attribs))) WARN("Failed to create a WGL context with wglCreateContextAttribsARB, last error %#x.\n", GetLastError()); @@ -2176,15 +2172,6 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain, gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ALIGNMENT, 1); checkGLcall("glPixelStorei(GL_UNPACK_ALIGNMENT, 1);"); - if (gl_info->supported[ARB_VERTEX_BLEND]) - { - /* Direct3D always uses n-1 weights for n world matrices and uses - * 1 - sum for the last one this is equal to GL_WEIGHT_SUM_UNITY_ARB. - * Enabling it doesn't do anything unless GL_VERTEX_BLEND_ARB isn't - * enabled as well. */ - gl_info->gl_ops.gl.p_glEnable(GL_WEIGHT_SUM_UNITY_ARB); - checkGLcall("glEnable(GL_WEIGHT_SUM_UNITY_ARB)"); - } if (gl_info->supported[NV_TEXTURE_SHADER2]) { /* Set up the previous texture input for all shader units. This applies to bump mapping, and in d3d @@ -2270,6 +2257,10 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain, if (device->dummy_textures.tex_2d) context_bind_dummy_textures(device, ret); + /* Initialise all rectangles to avoid resetting unused ones later. */ + gl_info->gl_ops.gl.p_glScissor(0, 0, 0, 0); + checkGLcall("glScissor"); + TRACE("Created context %p.\n", ret); return ret; @@ -2368,28 +2359,6 @@ const DWORD *context_get_tex_unit_mapping(const struct wined3d_context *context, return context->tex_unit_map; } -/* Context activation is done by the caller. */ -static void set_blit_dimension(const struct wined3d_gl_info *gl_info, UINT width, UINT height) -{ - const GLdouble projection[] = - { - 2.0 / width, 0.0, 0.0, 0.0, - 0.0, 2.0 / height, 0.0, 0.0, - 0.0, 0.0, 2.0, 0.0, - -1.0, -1.0, -1.0, 1.0, - }; - - if (gl_info->supported[WINED3D_GL_LEGACY_CONTEXT]) - { - gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION); - checkGLcall("glMatrixMode(GL_PROJECTION)"); - gl_info->gl_ops.gl.p_glLoadMatrixd(projection); - checkGLcall("glLoadMatrixd"); - } - gl_info->gl_ops.gl.p_glViewport(0, 0, width, height); - checkGLcall("glViewport"); -} - static void context_get_rt_size(const struct wined3d_context *context, SIZE *size) { const struct wined3d_texture *rt = context->current_rt.texture; @@ -2438,206 +2407,6 @@ void context_enable_clip_distances(struct wined3d_context *context, unsigned int checkGLcall("toggle clip distances"); } -/***************************************************************************** - * SetupForBlit - * - * Sets up a context for DirectDraw blitting. - * All texture units are disabled, texture unit 0 is set as current unit - * fog, lighting, blending, alpha test, z test, scissor test, culling disabled - * color writing enabled for all channels - * register combiners disabled, shaders disabled - * world matrix is set to identity, texture matrix 0 too - * projection matrix is setup for drawing screen coordinates - * - * Params: - * This: Device to activate the context for - * context: Context to setup - * - *****************************************************************************/ -/* Context activation is done by the caller. */ -static void SetupForBlit(const struct wined3d_device *device, struct wined3d_context *context) -{ - const struct wined3d_gl_info *gl_info = context->gl_info; - DWORD sampler; - SIZE rt_size; - int i; - - TRACE("Setting up context %p for blitting\n", context); - - context_get_rt_size(context, &rt_size); - - if (context->last_was_blit) - { - if (context->blit_w != rt_size.cx || context->blit_h != rt_size.cy) - { - set_blit_dimension(gl_info, rt_size.cx, rt_size.cy); - context->blit_w = rt_size.cx; - context->blit_h = rt_size.cy; - /* No need to dirtify here, the states are still dirtified because - * they weren't applied since the last SetupForBlit() call. */ - } - TRACE("Context is already set up for blitting, nothing to do\n"); - return; - } - context->last_was_blit = TRUE; - - if (gl_info->supported[WINED3D_GL_LEGACY_CONTEXT]) - { - /* Disable all textures. The caller can then bind a texture it wants to blit - * from - * - * The blitting code uses (for now) the fixed function pipeline, so make sure to reset all fixed - * function texture unit. No need to care for higher samplers - */ - for (i = gl_info->limits.textures - 1; i > 0 ; --i) - { - sampler = context->rev_tex_unit_map[i]; - context_active_texture(context, gl_info, i); - - if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) - { - gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB); - checkGLcall("glDisable GL_TEXTURE_CUBE_MAP_ARB"); - } - gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D); - checkGLcall("glDisable GL_TEXTURE_3D"); - if (gl_info->supported[ARB_TEXTURE_RECTANGLE]) - { - gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB); - checkGLcall("glDisable GL_TEXTURE_RECTANGLE_ARB"); - } - gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D); - checkGLcall("glDisable GL_TEXTURE_2D"); - - gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);"); - - if (sampler != WINED3D_UNMAPPED_STAGE) - { - if (sampler < MAX_TEXTURES) - context_invalidate_state(context, STATE_TEXTURESTAGE(sampler, WINED3D_TSS_COLOR_OP)); - context_invalidate_state(context, STATE_SAMPLER(sampler)); - } - } - - context_active_texture(context, gl_info, 0); - if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) - { - gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB); - checkGLcall("glDisable GL_TEXTURE_CUBE_MAP_ARB"); - } - gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D); - checkGLcall("glDisable GL_TEXTURE_3D"); - if (gl_info->supported[ARB_TEXTURE_RECTANGLE]) - { - gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB); - checkGLcall("glDisable GL_TEXTURE_RECTANGLE_ARB"); - } - gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D); - checkGLcall("glDisable GL_TEXTURE_2D"); - - gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - - gl_info->gl_ops.gl.p_glMatrixMode(GL_TEXTURE); - checkGLcall("glMatrixMode(GL_TEXTURE)"); - gl_info->gl_ops.gl.p_glLoadIdentity(); - checkGLcall("glLoadIdentity()"); - - if (gl_info->supported[EXT_TEXTURE_LOD_BIAS]) - { - gl_info->gl_ops.gl.p_glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, - GL_TEXTURE_LOD_BIAS_EXT, 0.0f); - checkGLcall("glTexEnvf GL_TEXTURE_LOD_BIAS_EXT ..."); - } - - /* Setup transforms */ - gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW); - checkGLcall("glMatrixMode(GL_MODELVIEW)"); - gl_info->gl_ops.gl.p_glLoadIdentity(); - checkGLcall("glLoadIdentity()"); - context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0))); - - /* Other misc states */ - gl_info->gl_ops.gl.p_glDisable(GL_ALPHA_TEST); - checkGLcall("glDisable(GL_ALPHA_TEST)"); - context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ALPHATESTENABLE)); - gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING); - checkGLcall("glDisable GL_LIGHTING"); - context_invalidate_state(context, STATE_RENDER(WINED3D_RS_LIGHTING)); - glDisableWINE(GL_FOG); - checkGLcall("glDisable GL_FOG"); - context_invalidate_state(context, STATE_RENDER(WINED3D_RS_FOGENABLE)); - } - - if (gl_info->supported[ARB_SAMPLER_OBJECTS]) - GL_EXTCALL(glBindSampler(0, 0)); - context_active_texture(context, gl_info, 0); - - sampler = context->rev_tex_unit_map[0]; - if (sampler != WINED3D_UNMAPPED_STAGE) - { - if (sampler < MAX_TEXTURES) - { - context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_TEXTURE0 + sampler)); - context_invalidate_state(context, STATE_TEXTURESTAGE(sampler, WINED3D_TSS_COLOR_OP)); - } - context_invalidate_state(context, STATE_SAMPLER(sampler)); - } - - /* Other misc states */ - gl_info->gl_ops.gl.p_glDisable(GL_DEPTH_TEST); - checkGLcall("glDisable GL_DEPTH_TEST"); - context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ZENABLE)); - gl_info->gl_ops.gl.p_glDisable(GL_BLEND); - checkGLcall("glDisable GL_BLEND"); - context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE)); - gl_info->gl_ops.gl.p_glDisable(GL_CULL_FACE); - checkGLcall("glDisable GL_CULL_FACE"); - context_invalidate_state(context, STATE_RENDER(WINED3D_RS_CULLMODE)); - gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST); - checkGLcall("glDisable GL_STENCIL_TEST"); - context_invalidate_state(context, STATE_RENDER(WINED3D_RS_STENCILENABLE)); - gl_info->gl_ops.gl.p_glDisable(GL_SCISSOR_TEST); - checkGLcall("glDisable GL_SCISSOR_TEST"); - context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SCISSORTESTENABLE)); - if (gl_info->supported[ARB_POINT_SPRITE]) - { - gl_info->gl_ops.gl.p_glDisable(GL_POINT_SPRITE_ARB); - checkGLcall("glDisable GL_POINT_SPRITE_ARB"); - context_invalidate_state(context, STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE)); - } - gl_info->gl_ops.gl.p_glColorMask(GL_TRUE, GL_TRUE,GL_TRUE,GL_TRUE); - checkGLcall("glColorMask"); - for (i = 0; i < MAX_RENDER_TARGETS; ++i) - context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITE(i))); - if (gl_info->supported[EXT_SECONDARY_COLOR]) - { - gl_info->gl_ops.gl.p_glDisable(GL_COLOR_SUM_EXT); - context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SPECULARENABLE)); - checkGLcall("glDisable(GL_COLOR_SUM_EXT)"); - } - - context->last_was_rhw = TRUE; - context_invalidate_state(context, STATE_VDECL); /* because of last_was_rhw = TRUE */ - - context_enable_clip_distances(context, 0); - context_invalidate_state(context, STATE_RENDER(WINED3D_RS_CLIPPING)); - - /* FIXME: Make draw_textured_quad() able to work with a upper left origin. */ - if (gl_info->supported[ARB_CLIP_CONTROL]) - GL_EXTCALL(glClipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE)); - - set_blit_dimension(gl_info, rt_size.cx, rt_size.cy); - - /* Disable shaders */ - device->shader_backend->shader_disable(device->shader_priv, context); - - context->blit_w = rt_size.cx; - context->blit_h = rt_size.cy; - context_invalidate_state(context, STATE_VIEWPORT); - context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION)); -} - static inline BOOL is_rt_mask_onscreen(DWORD rt_mask) { return rt_mask & (1u << 31); @@ -2756,11 +2525,9 @@ void context_bind_texture(struct wined3d_context *context, GLenum target, GLuint break; case GL_TEXTURE_1D: gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D, textures->tex_1d); - checkGLcall("glBindTexture"); break; case GL_TEXTURE_1D_ARRAY: gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D_ARRAY, textures->tex_1d_array); - checkGLcall("glBindTexture"); break; case GL_TEXTURE_2D: gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, textures->tex_2d); @@ -2900,7 +2667,7 @@ static void context_set_render_offscreen(struct wined3d_context *context, BOOL o context_invalidate_state(context, STATE_SCISSORRECT); if (!context->gl_info->supported[ARB_CLIP_CONTROL]) { - context_invalidate_state(context, STATE_FRONTFACE); + context_invalidate_state(context, STATE_RASTERIZER); context_invalidate_state(context, STATE_POINTSPRITECOORDORIGIN); context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION)); } @@ -2967,12 +2734,12 @@ GLenum context_get_offscreen_gl_buffer(const struct wined3d_context *context) } } -static DWORD context_generate_rt_mask_no_fbo(const struct wined3d_context *context, struct wined3d_texture *rt) +static DWORD context_generate_rt_mask_no_fbo(const struct wined3d_context *context, struct wined3d_resource *rt) { - if (!rt || rt->resource.format->id == WINED3DFMT_NULL) + if (!rt || rt->format->id == WINED3DFMT_NULL) return 0; - else if (rt->swapchain) - return context_generate_rt_mask_from_resource(&rt->resource); + else if (rt->type != WINED3D_RTYPE_BUFFER && texture_from_resource(rt)->swapchain) + return context_generate_rt_mask_from_resource(rt); else return context_generate_rt_mask(context_get_offscreen_gl_buffer(context)); } @@ -2980,9 +2747,13 @@ static DWORD context_generate_rt_mask_no_fbo(const struct wined3d_context *conte /* Context activation is done by the caller. */ void context_apply_blit_state(struct wined3d_context *context, const struct wined3d_device *device) { + const struct wined3d_gl_info *gl_info = context->gl_info; struct wined3d_texture *rt = context->current_rt.texture; - struct wined3d_surface *surface; DWORD rt_mask, *cur_mask; + unsigned int i, sampler; + SIZE rt_size; + + TRACE("Setting up context %p for blitting.\n", context); if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) { @@ -2990,8 +2761,8 @@ void context_apply_blit_state(struct wined3d_context *context, const struct wine { wined3d_texture_load(rt, context, FALSE); - surface = rt->sub_resources[context->current_rt.sub_resource_idx].u.surface; - context_apply_fbo_state_blit(context, GL_FRAMEBUFFER, surface, NULL, rt->resource.draw_binding); + context_apply_fbo_state_blit(context, GL_FRAMEBUFFER, &rt->resource, + context->current_rt.sub_resource_idx, NULL, 0, rt->resource.draw_binding); if (rt->resource.format->id != WINED3DFMT_NULL) rt_mask = 1; else @@ -3006,7 +2777,7 @@ void context_apply_blit_state(struct wined3d_context *context, const struct wine } else { - rt_mask = context_generate_rt_mask_no_fbo(context, rt); + rt_mask = context_generate_rt_mask_no_fbo(context, &rt->resource); } cur_mask = context->current_fbo ? &context->current_fbo->rt_mask : &context->draw_buffers_mask; @@ -3021,76 +2792,270 @@ void context_apply_blit_state(struct wined3d_context *context, const struct wine { context_check_fbo_status(context, GL_FRAMEBUFFER); } - - SetupForBlit(device, context); context_invalidate_state(context, STATE_FRAMEBUFFER); -} - -static BOOL have_framebuffer_attachment(unsigned int rt_count, struct wined3d_rendertarget_view * const *rts, - const struct wined3d_rendertarget_view *ds) -{ - unsigned int i; - if (ds) - return TRUE; + context_get_rt_size(context, &rt_size); - for (i = 0; i < rt_count; ++i) + if (context->last_was_blit) { - if (rts[i] && rts[i]->format->id != WINED3DFMT_NULL) - return TRUE; + if (context->blit_w != rt_size.cx || context->blit_h != rt_size.cy) + { + gl_info->gl_ops.gl.p_glViewport(0, 0, rt_size.cx, rt_size.cy); + context->viewport_count = WINED3D_MAX_VIEWPORTS; + context->blit_w = rt_size.cx; + context->blit_h = rt_size.cy; + /* No need to dirtify here, the states are still dirtified because + * they weren't applied since the last context_apply_blit_state() + * call. */ + } + checkGLcall("blit state application"); + TRACE("Context is already set up for blitting, nothing to do.\n"); + return; } + context->last_was_blit = TRUE; - return FALSE; -} - -/* Context activation is done by the caller. */ -BOOL context_apply_clear_state(struct wined3d_context *context, const struct wined3d_state *state, - UINT rt_count, const struct wined3d_fb_state *fb) -{ - struct wined3d_rendertarget_view * const *rts = fb->render_targets; - struct wined3d_rendertarget_view *dsv = fb->depth_stencil; - const struct wined3d_gl_info *gl_info = context->gl_info; - DWORD rt_mask = 0, *cur_mask; - unsigned int i; + if (gl_info->supported[ARB_SAMPLER_OBJECTS]) + GL_EXTCALL(glBindSampler(0, 0)); + context_active_texture(context, gl_info, 0); - if (isStateDirty(context, STATE_FRAMEBUFFER) || fb != state->fb - || rt_count != gl_info->limits.buffers) + sampler = context->rev_tex_unit_map[0]; + if (sampler != WINED3D_UNMAPPED_STAGE) { - if (!have_framebuffer_attachment(rt_count, rts, dsv)) + if (sampler < MAX_TEXTURES) { - WARN("Invalid render target config, need at least one attachment.\n"); - return FALSE; + context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_TEXTURE0 + sampler)); + context_invalidate_state(context, STATE_TEXTURESTAGE(sampler, WINED3D_TSS_COLOR_OP)); } + context_invalidate_state(context, STATE_SAMPLER(sampler)); + } - if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) - { - context_validate_onscreen_formats(context, dsv); - - if (!rt_count || wined3d_resource_is_offscreen(rts[0]->resource)) - { - memset(context->blit_targets, 0, sizeof(context->blit_targets)); - for (i = 0; i < rt_count; ++i) - { - if (rts[i]) - { - context->blit_targets[i].gl_view = rts[i]->gl_view; - context->blit_targets[i].resource = rts[i]->resource; - context->blit_targets[i].sub_resource_idx = rts[i]->sub_resource_idx; - context->blit_targets[i].layer_count = rts[i]->layer_count; - } - if (rts[i] && rts[i]->format->id != WINED3DFMT_NULL) - rt_mask |= (1u << i); - } - context_apply_fbo_state(context, GL_FRAMEBUFFER, context->blit_targets, - wined3d_rendertarget_view_get_surface(dsv), - rt_count ? rts[0]->resource->draw_binding : 0, - dsv ? dsv->resource->draw_binding : 0); - } - else - { - context_apply_fbo_state(context, GL_FRAMEBUFFER, NULL, NULL, - WINED3D_LOCATION_DRAWABLE, WINED3D_LOCATION_DRAWABLE); - rt_mask = context_generate_rt_mask_from_resource(rts[0]->resource); + if (gl_info->supported[WINED3D_GL_LEGACY_CONTEXT]) + { + gl_info->gl_ops.gl.p_glDisable(GL_ALPHA_TEST); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ALPHATESTENABLE)); + } + gl_info->gl_ops.gl.p_glDisable(GL_DEPTH_TEST); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ZENABLE)); + gl_info->gl_ops.gl.p_glDisable(GL_BLEND); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE)); + gl_info->gl_ops.gl.p_glDisable(GL_CULL_FACE); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_CULLMODE)); + gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_STENCILENABLE)); + gl_info->gl_ops.gl.p_glDisable(GL_SCISSOR_TEST); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SCISSORTESTENABLE)); + if (gl_info->supported[ARB_POINT_SPRITE]) + { + gl_info->gl_ops.gl.p_glDisable(GL_POINT_SPRITE_ARB); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE)); + } + if (gl_info->supported[ARB_FRAMEBUFFER_SRGB]) + { + gl_info->gl_ops.gl.p_glDisable(GL_FRAMEBUFFER_SRGB); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE)); + } + gl_info->gl_ops.gl.p_glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + for (i = 0; i < MAX_RENDER_TARGETS; ++i) + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITE(i))); + + context->last_was_rhw = TRUE; + context_invalidate_state(context, STATE_VDECL); /* because of last_was_rhw = TRUE */ + + context_enable_clip_distances(context, 0); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_CLIPPING)); + + /* FIXME: Make draw_textured_quad() able to work with a upper left origin. */ + if (gl_info->supported[ARB_CLIP_CONTROL]) + GL_EXTCALL(glClipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE)); + gl_info->gl_ops.gl.p_glViewport(0, 0, rt_size.cx, rt_size.cy); + context->viewport_count = WINED3D_MAX_VIEWPORTS; + context_invalidate_state(context, STATE_VIEWPORT); + + device->shader_backend->shader_disable(device->shader_priv, context); + + context->blit_w = rt_size.cx; + context->blit_h = rt_size.cy; + + checkGLcall("blit state application"); +} + +static void context_apply_blit_projection(const struct wined3d_context *context, unsigned int w, unsigned int h) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + const GLdouble projection[] = + { + 2.0 / w, 0.0, 0.0, 0.0, + 0.0, 2.0 / h, 0.0, 0.0, + 0.0, 0.0, 2.0, 0.0, + -1.0, -1.0, -1.0, 1.0, + }; + + gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION); + gl_info->gl_ops.gl.p_glLoadMatrixd(projection); +} + +/* Setup OpenGL states for fixed-function blitting. */ +/* Context activation is done by the caller. */ +void context_apply_ffp_blit_state(struct wined3d_context *context, const struct wined3d_device *device) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + unsigned int i, sampler; + + if (!gl_info->supported[WINED3D_GL_LEGACY_CONTEXT]) + ERR("Applying fixed-function state without legacy context support.\n"); + + if (context->last_was_ffp_blit) + { + SIZE rt_size; + + context_get_rt_size(context, &rt_size); + if (context->blit_w != rt_size.cx || context->blit_h != rt_size.cy) + context_apply_blit_projection(context, rt_size.cx, rt_size.cy); + context_apply_blit_state(context, device); + + checkGLcall("ffp blit state application"); + return; + } + context->last_was_ffp_blit = TRUE; + + context_apply_blit_state(context, device); + + /* Disable all textures. The caller can then bind a texture it wants to blit + * from. */ + for (i = gl_info->limits.textures - 1; i > 0 ; --i) + { + context_active_texture(context, gl_info, i); + + if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) + gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB); + gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D); + if (gl_info->supported[ARB_TEXTURE_RECTANGLE]) + gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB); + gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D); + + gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + + sampler = context->rev_tex_unit_map[i]; + if (sampler != WINED3D_UNMAPPED_STAGE) + { + if (sampler < MAX_TEXTURES) + context_invalidate_state(context, STATE_TEXTURESTAGE(sampler, WINED3D_TSS_COLOR_OP)); + context_invalidate_state(context, STATE_SAMPLER(sampler)); + } + } + + context_active_texture(context, gl_info, 0); + + if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) + gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB); + gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D); + if (gl_info->supported[ARB_TEXTURE_RECTANGLE]) + gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB); + gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D); + + gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + if (gl_info->supported[EXT_TEXTURE_LOD_BIAS]) + gl_info->gl_ops.gl.p_glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0.0f); + + gl_info->gl_ops.gl.p_glMatrixMode(GL_TEXTURE); + gl_info->gl_ops.gl.p_glLoadIdentity(); + + /* Setup transforms. */ + gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW); + gl_info->gl_ops.gl.p_glLoadIdentity(); + context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0))); + context_apply_blit_projection(context, context->blit_w, context->blit_h); + context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION)); + + /* Other misc states. */ + gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_LIGHTING)); + glDisableWINE(GL_FOG); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_FOGENABLE)); + + if (gl_info->supported[EXT_SECONDARY_COLOR]) + { + gl_info->gl_ops.gl.p_glDisable(GL_COLOR_SUM_EXT); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SPECULARENABLE)); + } + checkGLcall("ffp blit state application"); +} + +static BOOL have_framebuffer_attachment(unsigned int rt_count, struct wined3d_rendertarget_view * const *rts, + const struct wined3d_rendertarget_view *ds) +{ + unsigned int i; + + if (ds) + return TRUE; + + for (i = 0; i < rt_count; ++i) + { + if (rts[i] && rts[i]->format->id != WINED3DFMT_NULL) + return TRUE; + } + + return FALSE; +} + +/* Context activation is done by the caller. */ +BOOL context_apply_clear_state(struct wined3d_context *context, const struct wined3d_state *state, + UINT rt_count, const struct wined3d_fb_state *fb) +{ + struct wined3d_rendertarget_view * const *rts = fb->render_targets; + struct wined3d_rendertarget_view *dsv = fb->depth_stencil; + const struct wined3d_gl_info *gl_info = context->gl_info; + DWORD rt_mask = 0, *cur_mask; + unsigned int i; + + if (isStateDirty(context, STATE_FRAMEBUFFER) || fb != state->fb + || rt_count != gl_info->limits.buffers) + { + if (!have_framebuffer_attachment(rt_count, rts, dsv)) + { + WARN("Invalid render target config, need at least one attachment.\n"); + return FALSE; + } + + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) + { + struct wined3d_rendertarget_info ds_info = {{0}}; + + context_validate_onscreen_formats(context, dsv); + + if (!rt_count || wined3d_resource_is_offscreen(rts[0]->resource)) + { + memset(context->blit_targets, 0, sizeof(context->blit_targets)); + for (i = 0; i < rt_count; ++i) + { + if (rts[i]) + { + context->blit_targets[i].gl_view = rts[i]->gl_view; + context->blit_targets[i].resource = rts[i]->resource; + context->blit_targets[i].sub_resource_idx = rts[i]->sub_resource_idx; + context->blit_targets[i].layer_count = rts[i]->layer_count; + } + if (rts[i] && rts[i]->format->id != WINED3DFMT_NULL) + rt_mask |= (1u << i); + } + + if (dsv) + { + ds_info.gl_view = dsv->gl_view; + ds_info.resource = dsv->resource; + ds_info.sub_resource_idx = dsv->sub_resource_idx; + ds_info.layer_count = dsv->layer_count; + } + + context_apply_fbo_state(context, GL_FRAMEBUFFER, context->blit_targets, &ds_info, + rt_count ? rts[0]->resource->draw_binding : 0, + dsv ? dsv->resource->draw_binding : 0); + } + else + { + context_apply_fbo_state(context, GL_FRAMEBUFFER, NULL, &ds_info, + WINED3D_LOCATION_DRAWABLE, WINED3D_LOCATION_DRAWABLE); + rt_mask = context_generate_rt_mask_from_resource(rts[0]->resource); } /* If the framebuffer is not the device's fb the device's fb has to be reapplied @@ -3100,8 +3065,7 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win } else { - rt_mask = context_generate_rt_mask_no_fbo(context, - rt_count ? wined3d_rendertarget_view_get_surface(rts[0])->container : NULL); + rt_mask = context_generate_rt_mask_no_fbo(context, rt_count ? rts[0]->resource : NULL); } } else if (wined3d_settings.offscreen_rendering_mode == ORM_FBO @@ -3115,8 +3079,7 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win } else { - rt_mask = context_generate_rt_mask_no_fbo(context, - rt_count ? wined3d_rendertarget_view_get_surface(rts[0])->container : NULL); + rt_mask = context_generate_rt_mask_no_fbo(context, rt_count ? rts[0]->resource : NULL); } cur_mask = context->current_fbo ? &context->current_fbo->rt_mask : &context->draw_buffers_mask; @@ -3134,6 +3097,7 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win } context->last_was_blit = FALSE; + context->last_was_ffp_blit = FALSE; /* Blending and clearing should be orthogonal, but tests on the nvidia * driver show that disabling blending when clearing improves the clearing @@ -3165,7 +3129,7 @@ static DWORD find_draw_buffers_mask(const struct wined3d_context *context, const unsigned int i; if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) - return context_generate_rt_mask_no_fbo(context, wined3d_rendertarget_view_get_surface(rts[0])->container); + return context_generate_rt_mask_no_fbo(context, rts[0]->resource); else if (!context->render_offscreen) return context_generate_rt_mask_from_resource(rts[0]->resource); @@ -3202,9 +3166,11 @@ void context_state_fb(struct wined3d_context *context, const struct wined3d_stat if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) { + struct wined3d_rendertarget_info ds_info = {{0}}; + if (!context->render_offscreen) { - context_apply_fbo_state(context, GL_FRAMEBUFFER, NULL, NULL, + context_apply_fbo_state(context, GL_FRAMEBUFFER, NULL, &ds_info, WINED3D_LOCATION_DRAWABLE, WINED3D_LOCATION_DRAWABLE); } else @@ -3225,8 +3191,16 @@ void context_state_fb(struct wined3d_context *context, const struct wined3d_stat if (!color_location) color_location = fb->render_targets[i]->resource->draw_binding; } - context_apply_fbo_state(context, GL_FRAMEBUFFER, context->blit_targets, - wined3d_rendertarget_view_get_surface(fb->depth_stencil), + + if (fb->depth_stencil) + { + ds_info.gl_view = fb->depth_stencil->gl_view; + ds_info.resource = fb->depth_stencil->resource; + ds_info.sub_resource_idx = fb->depth_stencil->sub_resource_idx; + ds_info.layer_count = fb->depth_stencil->layer_count; + } + + context_apply_fbo_state(context, GL_FRAMEBUFFER, context->blit_targets, &ds_info, color_location, fb->depth_stencil ? fb->depth_stencil->resource->draw_binding : 0); } } @@ -4053,6 +4027,7 @@ static BOOL context_apply_draw_state(struct wined3d_context *context, context->numDirtyEntries = 0; /* This makes the whole list clean */ context->last_was_blit = FALSE; + context->last_was_ffp_blit = FALSE; return TRUE; } @@ -4114,6 +4089,7 @@ static void context_apply_compute_state(struct wined3d_context *context, context_invalidate_state(context, STATE_FRAMEBUFFER); context->last_was_blit = FALSE; + context->last_was_ffp_blit = FALSE; } static BOOL use_transform_feedback(const struct wined3d_state *state) @@ -4377,9 +4353,6 @@ void dispatch_compute(struct wined3d_device *device, const struct wined3d_state GL_EXTCALL(glMemoryBarrier(GL_ALL_BARRIER_BITS)); checkGLcall("glMemoryBarrier"); - if (wined3d_settings.strict_draw_ordering) - gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ - context_release(context); } @@ -4565,6 +4538,7 @@ static const BYTE *software_vertex_blending(struct wined3d_context *context, case WINED3D_FFP_EMIT_FLOAT4: vector[3] = data[3]; case WINED3D_FFP_EMIT_FLOAT3: vector[2] = data[2]; case WINED3D_FFP_EMIT_FLOAT2: vector[1] = data[1]; + case WINED3D_FFP_EMIT_FLOAT1: vector[0] = data[0]; break; default: FIXME("unsupported value format: %u\n", SI_FORMAT(element_idx)); return (BYTE *)data; @@ -5052,13 +5026,12 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s WARN_(d3d_perf)("Using software emulation because manual fog coordinates are provided.\n"); emulation = TRUE; } - else if (use_indexed_vertex_blending(state, stream_info) && use_software_vertex_processing(context->device)) + else if (use_indexed_vertex_blending(state, stream_info) && use_software_vertex_processing(context->device)) { WARN_(d3d_perf)("Using software emulation because application requested SVP.\n"); emulation = TRUE; } - if (emulation) { si_emulated = context->stream_info; @@ -5086,7 +5059,9 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s } else if (!context->transform_feedback_active) { - GLenum mode = gl_tfb_primitive_type_from_d3d(shader->u.gs.output_type); + enum wined3d_primitive_type primitive_type = shader->u.gs.output_type + ? shader->u.gs.output_type : d3d_primitive_type_from_gl(state->gl_primitive_type); + GLenum mode = gl_tfb_primitive_type_from_d3d(primitive_type); GL_EXTCALL(glBeginTransformFeedback(mode)); checkGLcall("glBeginTransformFeedback"); context->transform_feedback_active = 1; @@ -5141,8 +5116,663 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s for (i = 0; i < context->buffer_fence_count; ++i) wined3d_fence_issue(context->buffer_fences[i], device); - if (wined3d_settings.strict_draw_ordering) - gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ - context_release(context); } + +void context_unload_tex_coords(const struct wined3d_context *context) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + unsigned int texture_idx; + + for (texture_idx = 0; texture_idx < gl_info->limits.texture_coords; ++texture_idx) + { + gl_info->gl_ops.ext.p_glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx); + gl_info->gl_ops.gl.p_glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } +} + +void context_load_tex_coords(const struct wined3d_context *context, const struct wined3d_stream_info *si, + GLuint *current_bo, const struct wined3d_state *state) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + unsigned int mapped_stage = 0; + unsigned int texture_idx; + + for (texture_idx = 0; texture_idx < context->d3d_info->limits.ffp_blend_stages; ++texture_idx) + { + unsigned int coord_idx = state->texture_states[texture_idx][WINED3D_TSS_TEXCOORD_INDEX]; + + if ((mapped_stage = context->tex_unit_map[texture_idx]) == WINED3D_UNMAPPED_STAGE) + continue; + + if (mapped_stage >= gl_info->limits.texture_coords) + { + FIXME("Attempted to load unsupported texture coordinate %u.\n", mapped_stage); + continue; + } + + if (coord_idx < MAX_TEXTURES && (si->use_map & (1u << (WINED3D_FFP_TEXCOORD0 + coord_idx)))) + { + const struct wined3d_stream_info_element *e = &si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx]; + + TRACE("Setting up texture %u, idx %d, coord_idx %u, data {%#x:%p}.\n", + texture_idx, mapped_stage, coord_idx, e->data.buffer_object, e->data.addr); + + if (*current_bo != e->data.buffer_object) + { + GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, e->data.buffer_object)); + checkGLcall("glBindBuffer"); + *current_bo = e->data.buffer_object; + } + + GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage)); + checkGLcall("glClientActiveTextureARB"); + + /* The coords to supply depend completely on the fvf/vertex shader. */ + gl_info->gl_ops.gl.p_glTexCoordPointer(e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride, + e->data.addr + state->load_base_vertex_index * e->stride); + gl_info->gl_ops.gl.p_glEnableClientState(GL_TEXTURE_COORD_ARRAY); + } + else + { + GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1)); + } + } + if (gl_info->supported[NV_REGISTER_COMBINERS]) + { + /* The number of the mapped stages increases monotonically, so it's fine to use the last used one. */ + for (texture_idx = mapped_stage + 1; texture_idx < gl_info->limits.textures; ++texture_idx) + { + GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1)); + } + } + + checkGLcall("loadTexCoords"); +} + +/* This should match any arrays loaded in context_load_vertex_data(). */ +static void context_unload_vertex_data(struct wined3d_context *context) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + + if (!context->namedArraysLoaded) + return; + gl_info->gl_ops.gl.p_glDisableClientState(GL_VERTEX_ARRAY); + gl_info->gl_ops.gl.p_glDisableClientState(GL_NORMAL_ARRAY); + gl_info->gl_ops.gl.p_glDisableClientState(GL_COLOR_ARRAY); + if (gl_info->supported[EXT_SECONDARY_COLOR]) + gl_info->gl_ops.gl.p_glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT); + context_unload_tex_coords(context); + context->namedArraysLoaded = FALSE; +} + +static void context_load_vertex_data(struct wined3d_context *context, + const struct wined3d_stream_info *si, const struct wined3d_state *state) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + const struct wined3d_stream_info_element *e; + GLuint current_bo; + + TRACE("context %p, si %p, state %p.\n", context, si, state); + + /* This is used for the fixed-function pipeline only, and the + * fixed-function pipeline doesn't do instancing. */ + context->instance_count = 0; + current_bo = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0u : 0; + + /* Blend data */ + if ((si->use_map & (1u << WINED3D_FFP_BLENDWEIGHT)) + || si->use_map & (1u << WINED3D_FFP_BLENDINDICES)) + { + /* TODO: Support vertex blending in immediate mode draws. No need to + * write a FIXME here, this is done after the general vertex + * declaration decoding. */ + WARN("Vertex blending not supported.\n"); + } + + /* Point Size */ + if (si->use_map & (1u << WINED3D_FFP_PSIZE)) + { + /* No such functionality in the fixed-function GL pipeline. */ + WARN("Per-vertex point size not supported.\n"); + } + + /* Position */ + if (si->use_map & (1u << WINED3D_FFP_POSITION)) + { + e = &si->elements[WINED3D_FFP_POSITION]; + + if (current_bo != e->data.buffer_object) + { + GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, e->data.buffer_object)); + checkGLcall("glBindBuffer"); + current_bo = e->data.buffer_object; + } + + TRACE("glVertexPointer(%#x, %#x, %#x, %p);\n", + e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride, + e->data.addr + state->load_base_vertex_index * e->stride); + gl_info->gl_ops.gl.p_glVertexPointer(e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride, + e->data.addr + state->load_base_vertex_index * e->stride); + checkGLcall("glVertexPointer(...)"); + gl_info->gl_ops.gl.p_glEnableClientState(GL_VERTEX_ARRAY); + checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)"); + } + + /* Normals */ + if (si->use_map & (1u << WINED3D_FFP_NORMAL)) + { + e = &si->elements[WINED3D_FFP_NORMAL]; + + if (current_bo != e->data.buffer_object) + { + GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, e->data.buffer_object)); + checkGLcall("glBindBuffer"); + current_bo = e->data.buffer_object; + } + + TRACE("glNormalPointer(%#x, %#x, %p);\n", e->format->gl_vtx_type, e->stride, + e->data.addr + state->load_base_vertex_index * e->stride); + gl_info->gl_ops.gl.p_glNormalPointer(e->format->gl_vtx_type, e->stride, + e->data.addr + state->load_base_vertex_index * e->stride); + checkGLcall("glNormalPointer(...)"); + gl_info->gl_ops.gl.p_glEnableClientState(GL_NORMAL_ARRAY); + checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)"); + + } + else + { + gl_info->gl_ops.gl.p_glNormal3f(0, 0, 0); + checkGLcall("glNormal3f(0, 0, 0)"); + } + + /* Diffuse colour */ + if (si->use_map & (1u << WINED3D_FFP_DIFFUSE)) + { + e = &si->elements[WINED3D_FFP_DIFFUSE]; + + if (current_bo != e->data.buffer_object) + { + GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, e->data.buffer_object)); + checkGLcall("glBindBuffer"); + current_bo = e->data.buffer_object; + } + + TRACE("glColorPointer(%#x, %#x %#x, %p);\n", + e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride, + e->data.addr + state->load_base_vertex_index * e->stride); + gl_info->gl_ops.gl.p_glColorPointer(e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride, + e->data.addr + state->load_base_vertex_index * e->stride); + checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)"); + gl_info->gl_ops.gl.p_glEnableClientState(GL_COLOR_ARRAY); + checkGLcall("glEnableClientState(GL_COLOR_ARRAY)"); + + } + else + { + gl_info->gl_ops.gl.p_glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + checkGLcall("glColor4f(1, 1, 1, 1)"); + } + + /* Specular colour */ + if (si->use_map & (1u << WINED3D_FFP_SPECULAR)) + { + TRACE("Setting specular colour.\n"); + + e = &si->elements[WINED3D_FFP_SPECULAR]; + + if (gl_info->supported[EXT_SECONDARY_COLOR]) + { + GLenum type = e->format->gl_vtx_type; + GLint format = e->format->gl_vtx_format; + + if (current_bo != e->data.buffer_object) + { + GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, e->data.buffer_object)); + checkGLcall("glBindBuffer"); + current_bo = e->data.buffer_object; + } + + if (format != 4 || (gl_info->quirks & WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA)) + { + /* Usually specular colors only allow 3 components, since they have no alpha. In D3D, the specular alpha + * contains the fog coordinate, which is passed to GL with GL_EXT_fog_coord. However, the fixed function + * vertex pipeline can pass the specular alpha through, and pixel shaders can read it. So it GL accepts + * 4 component secondary colors use it + */ + TRACE("glSecondaryColorPointer(%#x, %#x, %#x, %p);\n", format, type, e->stride, + e->data.addr + state->load_base_vertex_index * e->stride); + GL_EXTCALL(glSecondaryColorPointerEXT(format, type, e->stride, + e->data.addr + state->load_base_vertex_index * e->stride)); + checkGLcall("glSecondaryColorPointerEXT(format, type, ...)"); + } + else + { + switch (type) + { + case GL_UNSIGNED_BYTE: + TRACE("glSecondaryColorPointer(3, GL_UNSIGNED_BYTE, %#x, %p);\n", e->stride, + e->data.addr + state->load_base_vertex_index * e->stride); + GL_EXTCALL(glSecondaryColorPointerEXT(3, GL_UNSIGNED_BYTE, e->stride, + e->data.addr + state->load_base_vertex_index * e->stride)); + checkGLcall("glSecondaryColorPointerEXT(3, GL_UNSIGNED_BYTE, ...)"); + break; + + default: + FIXME("Add 4 component specular colour pointers for type %#x.\n", type); + /* Make sure that the right colour component is dropped. */ + TRACE("glSecondaryColorPointer(3, %#x, %#x, %p);\n", type, e->stride, + e->data.addr + state->load_base_vertex_index * e->stride); + GL_EXTCALL(glSecondaryColorPointerEXT(3, type, e->stride, + e->data.addr + state->load_base_vertex_index * e->stride)); + checkGLcall("glSecondaryColorPointerEXT(3, type, ...)"); + } + } + gl_info->gl_ops.gl.p_glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT); + checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)"); + } + else + { + WARN("Specular colour is not supported in this GL implementation.\n"); + } + } + else + { + if (gl_info->supported[EXT_SECONDARY_COLOR]) + { + GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0); + checkGLcall("glSecondaryColor3fEXT(0, 0, 0)"); + } + else + { + WARN("Specular colour is not supported in this GL implementation.\n"); + } + } + + /* Texture coordinates */ + context_load_tex_coords(context, si, ¤t_bo, state); +} + +static void context_unload_numbered_array(struct wined3d_context *context, unsigned int i) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + + GL_EXTCALL(glDisableVertexAttribArray(i)); + checkGLcall("glDisableVertexAttribArray"); + if (gl_info->supported[ARB_INSTANCED_ARRAYS]) + GL_EXTCALL(glVertexAttribDivisor(i, 0)); + + context->numbered_array_mask &= ~(1u << i); +} + +static void context_unload_numbered_arrays(struct wined3d_context *context) +{ + unsigned int i; + + while (context->numbered_array_mask) + { + i = wined3d_bit_scan(&context->numbered_array_mask); + context_unload_numbered_array(context, i); + } +} + +static void context_load_numbered_arrays(struct wined3d_context *context, + const struct wined3d_stream_info *stream_info, const struct wined3d_state *state) +{ + const struct wined3d_shader *vs = state->shader[WINED3D_SHADER_TYPE_VERTEX]; + const struct wined3d_gl_info *gl_info = context->gl_info; + GLuint current_bo; + unsigned int i; + + /* Default to no instancing. */ + context->instance_count = 0; + current_bo = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0u : 0; + + for (i = 0; i < MAX_ATTRIBS; ++i) + { + const struct wined3d_stream_info_element *element = &stream_info->elements[i]; + const struct wined3d_stream_state *stream; + + if (!(stream_info->use_map & (1u << i))) + { + if (context->numbered_array_mask & (1u << i)) + context_unload_numbered_array(context, i); + if (!use_vs(state) && i == WINED3D_FFP_DIFFUSE) + GL_EXTCALL(glVertexAttrib4f(i, 1.0f, 1.0f, 1.0f, 1.0f)); + else + GL_EXTCALL(glVertexAttrib4f(i, 0.0f, 0.0f, 0.0f, 0.0f)); + continue; + } + + stream = &state->streams[element->stream_idx]; + + if ((stream->flags & WINED3DSTREAMSOURCE_INSTANCEDATA) && !context->instance_count) + context->instance_count = state->streams[0].frequency ? state->streams[0].frequency : 1; + + if (gl_info->supported[ARB_INSTANCED_ARRAYS]) + { + GL_EXTCALL(glVertexAttribDivisor(i, element->divisor)); + } + else if (element->divisor) + { + /* Unload instanced arrays, they will be loaded using immediate + * mode instead. */ + if (context->numbered_array_mask & (1u << i)) + context_unload_numbered_array(context, i); + continue; + } + + TRACE("Loading array %u [VBO=%u].\n", i, element->data.buffer_object); + + if (element->stride) + { + if (current_bo != element->data.buffer_object) + { + GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, element->data.buffer_object)); + checkGLcall("glBindBuffer"); + current_bo = element->data.buffer_object; + } + /* Use the VBO to find out if a vertex buffer exists, not the vb + * pointer. vb can point to a user pointer data blob. In that case + * current_bo will be 0. If there is a vertex buffer but no vbo we + * won't be load converted attributes anyway. */ + if (vs && vs->reg_maps.shader_version.major >= 4 + && (element->format->flags[WINED3D_GL_RES_TYPE_BUFFER] & WINED3DFMT_FLAG_INTEGER)) + { + GL_EXTCALL(glVertexAttribIPointer(i, element->format->gl_vtx_format, element->format->gl_vtx_type, + element->stride, element->data.addr + state->load_base_vertex_index * element->stride)); + } + else + { + GL_EXTCALL(glVertexAttribPointer(i, element->format->gl_vtx_format, element->format->gl_vtx_type, + element->format->gl_normalized, element->stride, + element->data.addr + state->load_base_vertex_index * element->stride)); + } + + if (!(context->numbered_array_mask & (1u << i))) + { + GL_EXTCALL(glEnableVertexAttribArray(i)); + context->numbered_array_mask |= (1u << i); + } + } + else + { + /* Stride = 0 means always the same values. + * glVertexAttribPointer() doesn't do that. Instead disable the + * pointer and set up the attribute statically. But we have to + * figure out the system memory address. */ + const BYTE *ptr = element->data.addr; + if (element->data.buffer_object) + ptr += (ULONG_PTR)wined3d_buffer_load_sysmem(stream->buffer, context); + + if (context->numbered_array_mask & (1u << i)) + context_unload_numbered_array(context, i); + + switch (element->format->id) + { + case WINED3DFMT_R32_FLOAT: + GL_EXTCALL(glVertexAttrib1fv(i, (const GLfloat *)ptr)); + break; + case WINED3DFMT_R32G32_FLOAT: + GL_EXTCALL(glVertexAttrib2fv(i, (const GLfloat *)ptr)); + break; + case WINED3DFMT_R32G32B32_FLOAT: + GL_EXTCALL(glVertexAttrib3fv(i, (const GLfloat *)ptr)); + break; + case WINED3DFMT_R32G32B32A32_FLOAT: + GL_EXTCALL(glVertexAttrib4fv(i, (const GLfloat *)ptr)); + break; + case WINED3DFMT_R8G8B8A8_UINT: + GL_EXTCALL(glVertexAttrib4ubv(i, ptr)); + break; + case WINED3DFMT_B8G8R8A8_UNORM: + if (gl_info->supported[ARB_VERTEX_ARRAY_BGRA]) + { + const DWORD *src = (const DWORD *)ptr; + DWORD c = *src & 0xff00ff00u; + c |= (*src & 0xff0000u) >> 16; + c |= (*src & 0xffu) << 16; + GL_EXTCALL(glVertexAttrib4Nubv(i, (GLubyte *)&c)); + break; + } + /* else fallthrough */ + case WINED3DFMT_R8G8B8A8_UNORM: + GL_EXTCALL(glVertexAttrib4Nubv(i, ptr)); + break; + case WINED3DFMT_R16G16_SINT: + GL_EXTCALL(glVertexAttrib2sv(i, (const GLshort *)ptr)); + break; + case WINED3DFMT_R16G16B16A16_SINT: + GL_EXTCALL(glVertexAttrib4sv(i, (const GLshort *)ptr)); + break; + case WINED3DFMT_R16G16_SNORM: + { + const GLshort s[4] = {((const GLshort *)ptr)[0], ((const GLshort *)ptr)[1], 0, 1}; + GL_EXTCALL(glVertexAttrib4Nsv(i, s)); + break; + } + case WINED3DFMT_R16G16_UNORM: + { + const GLushort s[4] = {((const GLushort *)ptr)[0], ((const GLushort *)ptr)[1], 0, 1}; + GL_EXTCALL(glVertexAttrib4Nusv(i, s)); + break; + } + case WINED3DFMT_R16G16B16A16_SNORM: + GL_EXTCALL(glVertexAttrib4Nsv(i, (const GLshort *)ptr)); + break; + case WINED3DFMT_R16G16B16A16_UNORM: + GL_EXTCALL(glVertexAttrib4Nusv(i, (const GLushort *)ptr)); + break; + case WINED3DFMT_R10G10B10X2_UINT: + FIXME("Unsure about WINED3DDECLTYPE_UDEC3.\n"); + /*glVertexAttrib3usvARB(i, (const GLushort *)ptr); Does not exist */ + break; + case WINED3DFMT_R10G10B10X2_SNORM: + FIXME("Unsure about WINED3DDECLTYPE_DEC3N.\n"); + /*glVertexAttrib3NusvARB(i, (const GLushort *)ptr); Does not exist */ + break; + case WINED3DFMT_R16G16_FLOAT: + if (gl_info->supported[NV_HALF_FLOAT] && gl_info->supported[NV_VERTEX_PROGRAM]) + { + /* Not supported by GL_ARB_half_float_vertex. */ + GL_EXTCALL(glVertexAttrib2hvNV(i, (const GLhalfNV *)ptr)); + } + else + { + float x = float_16_to_32(((const unsigned short *)ptr) + 0); + float y = float_16_to_32(((const unsigned short *)ptr) + 1); + GL_EXTCALL(glVertexAttrib2f(i, x, y)); + } + break; + case WINED3DFMT_R16G16B16A16_FLOAT: + if (gl_info->supported[NV_HALF_FLOAT] && gl_info->supported[NV_VERTEX_PROGRAM]) + { + /* Not supported by GL_ARB_half_float_vertex. */ + GL_EXTCALL(glVertexAttrib4hvNV(i, (const GLhalfNV *)ptr)); + } + else + { + float x = float_16_to_32(((const unsigned short *)ptr) + 0); + float y = float_16_to_32(((const unsigned short *)ptr) + 1); + float z = float_16_to_32(((const unsigned short *)ptr) + 2); + float w = float_16_to_32(((const unsigned short *)ptr) + 3); + GL_EXTCALL(glVertexAttrib4f(i, x, y, z, w)); + } + break; + default: + ERR("Unexpected declaration in stride 0 attributes.\n"); + break; + + } + } + } + checkGLcall("Loading numbered arrays"); +} + +void context_update_stream_sources(struct wined3d_context *context, const struct wined3d_state *state) +{ + + if (context->use_immediate_mode_draw) + return; + + context_unload_vertex_data(context); + if (context->d3d_info->ffp_generic_attributes || use_vs(state)) + { + TRACE("Loading numbered arrays.\n"); + context_load_numbered_arrays(context, &context->stream_info, state); + return; + } + + TRACE("Loading named arrays.\n"); + context_unload_numbered_arrays(context); + context_load_vertex_data(context, &context->stream_info, state); + context->namedArraysLoaded = TRUE; +} + +static void apply_texture_blit_state(const struct wined3d_gl_info *gl_info, struct gl_texture *texture, + GLenum target, unsigned int level, enum wined3d_texture_filter_type filter) +{ + gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_MAG_FILTER, wined3d_gl_mag_filter(filter)); + gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_MIN_FILTER, + wined3d_gl_min_mip_filter(filter, WINED3D_TEXF_NONE)); + gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE]) + gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT); + gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, level); + + /* We changed the filtering settings on the texture. Make sure they get + * reset on subsequent draws. */ + texture->sampler_desc.mag_filter = WINED3D_TEXF_POINT; + texture->sampler_desc.min_filter = WINED3D_TEXF_POINT; + texture->sampler_desc.mip_filter = WINED3D_TEXF_NONE; + texture->sampler_desc.address_u = WINED3D_TADDRESS_CLAMP; + texture->sampler_desc.address_v = WINED3D_TADDRESS_CLAMP; + texture->sampler_desc.srgb_decode = FALSE; + texture->base_level = level; +} + +/* Context activation is done by the caller. */ +void context_draw_shaded_quad(struct wined3d_context *context, struct wined3d_texture *texture, + unsigned int sub_resource_idx, const RECT *src_rect, const RECT *dst_rect, + enum wined3d_texture_filter_type filter) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + struct wined3d_blt_info info; + unsigned int level, w, h, i; + SIZE dst_size; + struct blit_vertex + { + float x, y; + struct wined3d_vec3 texcoord; + } + quad[4]; + + texture2d_get_blt_info(texture, sub_resource_idx, src_rect, &info); + + level = sub_resource_idx % texture->level_count; + context_bind_texture(context, info.bind_target, texture->texture_rgb.name); + apply_texture_blit_state(gl_info, &texture->texture_rgb, info.bind_target, level, filter); + gl_info->gl_ops.gl.p_glTexParameteri(info.bind_target, GL_TEXTURE_MAX_LEVEL, level); + + context_get_rt_size(context, &dst_size); + w = dst_size.cx; + h = dst_size.cy; + + quad[0].x = dst_rect->left * 2.0f / w - 1.0f; + quad[0].y = dst_rect->top * 2.0f / h - 1.0f; + quad[0].texcoord = info.texcoords[0]; + + quad[1].x = dst_rect->right * 2.0f / w - 1.0f; + quad[1].y = dst_rect->top * 2.0f / h - 1.0f; + quad[1].texcoord = info.texcoords[1]; + + quad[2].x = dst_rect->left * 2.0f / w - 1.0f; + quad[2].y = dst_rect->bottom * 2.0f / h - 1.0f; + quad[2].texcoord = info.texcoords[2]; + + quad[3].x = dst_rect->right * 2.0f / w - 1.0f; + quad[3].y = dst_rect->bottom * 2.0f / h - 1.0f; + quad[3].texcoord = info.texcoords[3]; + + /* Draw a quad. */ + if (gl_info->supported[ARB_VERTEX_BUFFER_OBJECT]) + { + if (!context->blit_vbo) + GL_EXTCALL(glGenBuffers(1, &context->blit_vbo)); + GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, context->blit_vbo)); + + context_unload_vertex_data(context); + context_unload_numbered_arrays(context); + + GL_EXTCALL(glBufferData(GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STREAM_DRAW)); + GL_EXTCALL(glVertexAttribPointer(0, 2, GL_FLOAT, FALSE, sizeof(*quad), NULL)); + GL_EXTCALL(glVertexAttribPointer(1, 3, GL_FLOAT, FALSE, sizeof(*quad), + (void *)FIELD_OFFSET(struct blit_vertex, texcoord))); + + GL_EXTCALL(glEnableVertexAttribArray(0)); + GL_EXTCALL(glEnableVertexAttribArray(1)); + + gl_info->gl_ops.gl.p_glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, 0)); + GL_EXTCALL(glDisableVertexAttribArray(1)); + GL_EXTCALL(glDisableVertexAttribArray(0)); + } + else + { + gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP); + + for (i = 0; i < ARRAY_SIZE(quad); ++i) + { + GL_EXTCALL(glVertexAttrib3fv(1, &quad[i].texcoord.x)); + GL_EXTCALL(glVertexAttrib2fv(0, &quad[i].x)); + } + + gl_info->gl_ops.gl.p_glEnd(); + } + checkGLcall("draw"); + + gl_info->gl_ops.gl.p_glTexParameteri(info.bind_target, GL_TEXTURE_MAX_LEVEL, texture->level_count - 1); + context_bind_texture(context, info.bind_target, 0); +} + +/* Context activation is done by the caller. */ +void context_draw_textured_quad(struct wined3d_context *context, struct wined3d_texture *texture, + unsigned int sub_resource_idx, const RECT *src_rect, const RECT *dst_rect, + enum wined3d_texture_filter_type filter) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + struct wined3d_blt_info info; + unsigned int level; + + texture2d_get_blt_info(texture, sub_resource_idx, src_rect, &info); + + gl_info->gl_ops.gl.p_glEnable(info.bind_target); + checkGLcall("glEnable(bind_target)"); + + level = sub_resource_idx % texture->level_count; + context_bind_texture(context, info.bind_target, texture->texture_rgb.name); + apply_texture_blit_state(gl_info, &texture->texture_rgb, info.bind_target, level, filter); + gl_info->gl_ops.gl.p_glTexParameteri(info.bind_target, GL_TEXTURE_MAX_LEVEL, level); + gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + checkGLcall("glTexEnvi"); + + /* Draw a quad. */ + gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP); + gl_info->gl_ops.gl.p_glTexCoord3fv(&info.texcoords[0].x); + gl_info->gl_ops.gl.p_glVertex2i(dst_rect->left, dst_rect->top); + + gl_info->gl_ops.gl.p_glTexCoord3fv(&info.texcoords[1].x); + gl_info->gl_ops.gl.p_glVertex2i(dst_rect->right, dst_rect->top); + + gl_info->gl_ops.gl.p_glTexCoord3fv(&info.texcoords[2].x); + gl_info->gl_ops.gl.p_glVertex2i(dst_rect->left, dst_rect->bottom); + + gl_info->gl_ops.gl.p_glTexCoord3fv(&info.texcoords[3].x); + gl_info->gl_ops.gl.p_glVertex2i(dst_rect->right, dst_rect->bottom); + gl_info->gl_ops.gl.p_glEnd(); + + gl_info->gl_ops.gl.p_glTexParameteri(info.bind_target, GL_TEXTURE_MAX_LEVEL, texture->level_count - 1); + context_bind_texture(context, info.bind_target, 0); +} diff --git a/dll/directx/wine/wined3d/cs.c b/dll/directx/wine/wined3d/cs.c index 460fe12c7d..eb24d94e9a 100644 --- a/dll/directx/wine/wined3d/cs.c +++ b/dll/directx/wine/wined3d/cs.c @@ -33,8 +33,8 @@ enum wined3d_cs_op WINED3D_CS_OP_DRAW, WINED3D_CS_OP_FLUSH, WINED3D_CS_OP_SET_PREDICATION, - WINED3D_CS_OP_SET_VIEWPORT, - WINED3D_CS_OP_SET_SCISSOR_RECT, + WINED3D_CS_OP_SET_VIEWPORTS, + WINED3D_CS_OP_SET_SCISSOR_RECTS, WINED3D_CS_OP_SET_RENDERTARGET_VIEW, WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW, WINED3D_CS_OP_SET_VERTEX_DECLARATION, @@ -94,7 +94,7 @@ struct wined3d_cs_present struct wined3d_swapchain *swapchain; RECT src_rect; RECT dst_rect; - DWORD swap_interval; + unsigned int swap_interval; DWORD flags; }; @@ -138,16 +138,18 @@ struct wined3d_cs_set_predication BOOL value; }; -struct wined3d_cs_set_viewport +struct wined3d_cs_set_viewports { enum wined3d_cs_op opcode; - struct wined3d_viewport viewport; + unsigned int viewport_count; + struct wined3d_viewport viewports[1]; }; -struct wined3d_cs_set_scissor_rect +struct wined3d_cs_set_scissor_rects { enum wined3d_cs_op opcode; - RECT rect; + unsigned int rect_count; + RECT rects[1]; }; struct wined3d_cs_set_rendertarget_view @@ -406,9 +408,7 @@ struct wined3d_cs_update_sub_resource unsigned int sub_resource_idx; struct wined3d_box box; struct wined3d_sub_resource_data data; -#if defined(STAGING_CSMT) BYTE copy_data[1]; -#endif /* STAGING_CSMT */ }; struct wined3d_cs_add_dirty_texture_region @@ -456,12 +456,7 @@ static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) swapchain = op->swapchain; wined3d_swapchain_set_window(swapchain, op->dst_window_override); - - if (op->swap_interval && swapchain->desc.swap_interval != op->swap_interval) - { - swapchain->desc.swap_interval = op->swap_interval; - swapchain_update_swap_interval(swapchain); - } + wined3d_swapchain_set_swap_interval(swapchain, op->swap_interval); swapchain->swapchain_ops->swapchain_present(swapchain, &op->src_rect, &op->dst_rect, op->flags); @@ -476,7 +471,7 @@ static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain, const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, - DWORD swap_interval, DWORD flags) + unsigned int swap_interval, DWORD flags) { struct wined3d_cs_present *op; unsigned int i; @@ -502,9 +497,8 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT); /* Limit input latency by limiting the number of presents that we can get - * ahead of the worker thread. We have a constant limit here, but - * IDXGIDevice1 allows tuning this. */ - while (pending > 1) + * ahead of the worker thread. */ + while (pending >= swapchain->max_frame_latency) { wined3d_pause(); pending = InterlockedCompareExchange(&cs->pending_presents, 0, 0); @@ -538,19 +532,24 @@ void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT * { unsigned int rt_count = cs->device->adapter->gl_info.limits.buffers; const struct wined3d_state *state = &cs->device->state; - const struct wined3d_viewport *vp = &state->viewport; + const struct wined3d_viewport *vp = &state->viewports[0]; + struct wined3d_rendertarget_view *view; struct wined3d_cs_clear *op; + RECT view_rect; unsigned int i; op = cs->ops->require_space(cs, FIELD_OFFSET(struct wined3d_cs_clear, rects[rect_count]), WINED3D_CS_QUEUE_DEFAULT); op->opcode = WINED3D_CS_OP_CLEAR; op->flags = flags; - op->rt_count = rt_count; + if (flags & WINED3DCLEAR_TARGET) + op->rt_count = rt_count; + else + op->rt_count = 0; op->fb = &cs->fb; SetRect(&op->draw_rect, vp->x, vp->y, vp->x + vp->width, vp->y + vp->height); if (state->render_states[WINED3D_RS_SCISSORTESTENABLE]) - IntersectRect(&op->draw_rect, &op->draw_rect, &state->scissor_rect); + IntersectRect(&op->draw_rect, &op->draw_rect, &state->scissor_rects[0]); op->color = *color; op->depth = depth; op->stencil = stencil; @@ -561,12 +560,21 @@ void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT * { for (i = 0; i < rt_count; ++i) { - if (state->fb->render_targets[i]) - wined3d_resource_acquire(state->fb->render_targets[i]->resource); + if ((view = state->fb->render_targets[i])) + { + SetRect(&view_rect, 0, 0, view->width, view->height); + IntersectRect(&op->draw_rect, &op->draw_rect, &view_rect); + wined3d_resource_acquire(view->resource); + } } } if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL)) - wined3d_resource_acquire(state->fb->depth_stencil->resource); + { + view = state->fb->depth_stencil; + SetRect(&view_rect, 0, 0, view->width, view->height); + IntersectRect(&op->draw_rect, &op->draw_rect, &view_rect); + wined3d_resource_acquire(view->resource); + } cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT); } @@ -774,6 +782,7 @@ void wined3d_cs_emit_dispatch_indirect(struct wined3d_cs *cs, static void wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data) { const struct wined3d_gl_info *gl_info = &cs->device->adapter->gl_info; + const struct wined3d_shader *geometry_shader; struct wined3d_state *state = &cs->state; const struct wined3d_cs_draw *op = data; int load_base_vertex_idx; @@ -793,6 +802,8 @@ static void wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data) if (state->gl_primitive_type != op->primitive_type) { + if ((geometry_shader = state->shader[WINED3D_SHADER_TYPE_GEOMETRY]) && !geometry_shader->function) + device_invalidate_state(cs->device, STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY)); if (state->gl_primitive_type == GL_POINTS || op->primitive_type == GL_POINTS) device_invalidate_state(cs->device, STATE_POINT_ENABLE); state->gl_primitive_type = op->primitive_type; @@ -958,40 +969,53 @@ void wined3d_cs_emit_set_predication(struct wined3d_cs *cs, struct wined3d_query cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT); } -static void wined3d_cs_exec_set_viewport(struct wined3d_cs *cs, const void *data) +static void wined3d_cs_exec_set_viewports(struct wined3d_cs *cs, const void *data) { - const struct wined3d_cs_set_viewport *op = data; + const struct wined3d_cs_set_viewports *op = data; - cs->state.viewport = op->viewport; + if (op->viewport_count) + memcpy(cs->state.viewports, op->viewports, op->viewport_count * sizeof(*op->viewports)); + else + memset(cs->state.viewports, 0, sizeof(*cs->state.viewports)); + cs->state.viewport_count = op->viewport_count; device_invalidate_state(cs->device, STATE_VIEWPORT); } -void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) +void wined3d_cs_emit_set_viewports(struct wined3d_cs *cs, unsigned int viewport_count, + const struct wined3d_viewport *viewports) { - struct wined3d_cs_set_viewport *op; + struct wined3d_cs_set_viewports *op; - op = cs->ops->require_space(cs, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT); - op->opcode = WINED3D_CS_OP_SET_VIEWPORT; - op->viewport = *viewport; + op = cs->ops->require_space(cs, FIELD_OFFSET(struct wined3d_cs_set_viewports, viewports[viewport_count]), + WINED3D_CS_QUEUE_DEFAULT); + op->opcode = WINED3D_CS_OP_SET_VIEWPORTS; + memcpy(op->viewports, viewports, viewport_count * sizeof(*viewports)); + op->viewport_count = viewport_count; cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT); } -static void wined3d_cs_exec_set_scissor_rect(struct wined3d_cs *cs, const void *data) +static void wined3d_cs_exec_set_scissor_rects(struct wined3d_cs *cs, const void *data) { - const struct wined3d_cs_set_scissor_rect *op = data; + const struct wined3d_cs_set_scissor_rects *op = data; - cs->state.scissor_rect = op->rect; + if (op->rect_count) + memcpy(cs->state.scissor_rects, op->rects, op->rect_count * sizeof(*op->rects)); + else + SetRectEmpty(cs->state.scissor_rects); + cs->state.scissor_rect_count = op->rect_count; device_invalidate_state(cs->device, STATE_SCISSORRECT); } -void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect) +void wined3d_cs_emit_set_scissor_rects(struct wined3d_cs *cs, unsigned int rect_count, const RECT *rects) { - struct wined3d_cs_set_scissor_rect *op; + struct wined3d_cs_set_scissor_rects *op; - op = cs->ops->require_space(cs, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT); - op->opcode = WINED3D_CS_OP_SET_SCISSOR_RECT; - op->rect = *rect; + op = cs->ops->require_space(cs, FIELD_OFFSET(struct wined3d_cs_set_scissor_rects, rects[rect_count]), + WINED3D_CS_QUEUE_DEFAULT); + op->opcode = WINED3D_CS_OP_SET_SCISSOR_RECTS; + memcpy(op->rects, rects, rect_count * sizeof(*rects)); + op->rect_count = rect_count; cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT); } @@ -1023,16 +1047,14 @@ static void wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs *cs, const struct wined3d_device *device = cs->device; struct wined3d_rendertarget_view *prev; - if ((prev = cs->state.fb->depth_stencil)) + if ((prev = cs->state.fb->depth_stencil) && prev->resource->type != WINED3D_RTYPE_BUFFER) { - struct wined3d_surface *prev_surface = wined3d_rendertarget_view_get_surface(prev); + struct wined3d_texture *prev_texture = texture_from_resource(prev->resource); - if (prev_surface && (device->swapchains[0]->desc.flags & WINED3D_SWAPCHAIN_DISCARD_DEPTHSTENCIL - || prev_surface->container->flags & WINED3D_TEXTURE_DISCARD)) - { - wined3d_texture_validate_location(prev_surface->container, + if (device->swapchains[0]->desc.flags & WINED3D_SWAPCHAIN_DISCARD_DEPTHSTENCIL + || prev_texture->flags & WINED3D_TEXTURE_DISCARD) + wined3d_texture_validate_location(prev_texture, prev->sub_resource_idx, WINED3D_LOCATION_DISCARDED); - } } cs->fb.depth_stencil = op->view; @@ -1470,7 +1492,7 @@ static void wined3d_cs_exec_set_rasterizer_state(struct wined3d_cs *cs, const vo const struct wined3d_cs_set_rasterizer_state *op = data; cs->state.rasterizer_state = op->state; - device_invalidate_state(cs->device, STATE_FRONTFACE); + device_invalidate_state(cs->device, STATE_RASTERIZER); } void wined3d_cs_emit_set_rasterizer_state(struct wined3d_cs *cs, @@ -2059,23 +2081,6 @@ static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs, const void * buffer_from_resource(op->src_resource), op->src_box.left, op->src_box.right - op->src_box.left); } - else if (op->dst_resource->type == WINED3D_RTYPE_TEXTURE_2D) - { - struct wined3d_surface *dst_surface, *src_surface; - struct wined3d_texture *dst_texture, *src_texture; - RECT dst_rect, src_rect; - - dst_texture = texture_from_resource(op->dst_resource); - src_texture = texture_from_resource(op->src_resource); - dst_surface = dst_texture->sub_resources[op->dst_sub_resource_idx].u.surface; - src_surface = src_texture->sub_resources[op->src_sub_resource_idx].u.surface; - SetRect(&dst_rect, op->dst_box.left, op->dst_box.top, op->dst_box.right, op->dst_box.bottom); - SetRect(&src_rect, op->src_box.left, op->src_box.top, op->src_box.right, op->src_box.bottom); - - if (FAILED(wined3d_surface_blt(dst_surface, &dst_rect, src_surface, - &src_rect, op->flags, &op->fx, op->filter))) - FIXME("Blit failed.\n"); - } else if (op->dst_resource->type == WINED3D_RTYPE_TEXTURE_3D) { struct wined3d_texture *src_texture, *dst_texture; @@ -2110,13 +2115,6 @@ static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs, const void * goto error; } - if (op->src_box.left || op->src_box.top || op->src_box.front) - { - FIXME("Source box %s not supported for %s resources.\n", - debug_box(&op->src_box), debug_d3dresourcetype(op->dst_resource->type)); - goto error; - } - dst_texture = texture_from_resource(op->dst_resource); src_texture = texture_from_resource(op->src_resource); @@ -2151,8 +2149,9 @@ static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs, const void * &row_pitch, &slice_pitch); wined3d_texture_bind_and_dirtify(dst_texture, context, FALSE); - wined3d_texture_upload_data(dst_texture, op->dst_sub_resource_idx, context, &op->dst_box, - wined3d_const_bo_address(&addr), row_pitch, slice_pitch); + wined3d_texture_upload_data(dst_texture, op->dst_sub_resource_idx, context, + dst_texture->resource.format, &op->src_box, wined3d_const_bo_address(&addr), + row_pitch, slice_pitch, op->dst_box.left, op->dst_box.top, op->dst_box.front, FALSE); wined3d_texture_validate_location(dst_texture, op->dst_sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB); wined3d_texture_invalidate_location(dst_texture, op->dst_sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB); @@ -2160,7 +2159,10 @@ static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs, const void * } else { - FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(op->dst_resource->type)); + if (FAILED(texture2d_blt(texture_from_resource(op->dst_resource), op->dst_sub_resource_idx, + &op->dst_box, texture_from_resource(op->src_resource), op->src_sub_resource_idx, + &op->src_box, op->flags, &op->fx, op->filter))) + FIXME("Blit failed.\n"); } error: @@ -2209,6 +2211,7 @@ static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const voi struct wined3d_const_bo_address addr; struct wined3d_context *context; struct wined3d_texture *texture; + struct wined3d_box src_box; context = context_acquire(cs->device, NULL, 0); @@ -2245,8 +2248,9 @@ static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const voi wined3d_texture_load_location(texture, op->sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB); wined3d_texture_bind_and_dirtify(texture, context, FALSE); - wined3d_texture_upload_data(texture, op->sub_resource_idx, context, - box, &addr, op->data.row_pitch, op->data.slice_pitch); + wined3d_box_set(&src_box, 0, 0, box->right - box->left, box->bottom - box->top, 0, box->back - box->front); + wined3d_texture_upload_data(texture, op->sub_resource_idx, context, texture->resource.format, &src_box, + &addr, op->data.row_pitch, op->data.slice_pitch, box->left, box->top, box->front, FALSE); wined3d_texture_validate_location(texture, op->sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB); wined3d_texture_invalidate_location(texture, op->sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB); @@ -2262,7 +2266,6 @@ void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_r unsigned int slice_pitch) { struct wined3d_cs_update_sub_resource *op; -#if defined(STAGING_CSMT) size_t data_size, size; if (resource->type != WINED3D_RTYPE_BUFFER && resource->format_flags & WINED3DFMT_FLAG_BLOCKS) @@ -2308,7 +2311,6 @@ void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_r no_async: wined3d_resource_wait_idle(resource); -#endif /* STAGING_CSMT */ op = cs->ops->require_space(cs, sizeof(*op), WINED3D_CS_QUEUE_MAP); op->opcode = WINED3D_CS_OP_UPDATE_SUB_RESOURCE; @@ -2322,10 +2324,6 @@ no_async: wined3d_resource_acquire(resource); cs->ops->submit(cs, WINED3D_CS_QUEUE_MAP); -#if !defined(STAGING_CSMT) - /* The data pointer may go away, so we need to wait until it is read. - * Copying the data may be faster if it's small. */ -#endif /* STAGING_CSMT */ cs->ops->finish(cs, WINED3D_CS_QUEUE_MAP); } @@ -2466,8 +2464,8 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void /* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw, /* WINED3D_CS_OP_FLUSH */ wined3d_cs_exec_flush, /* WINED3D_CS_OP_SET_PREDICATION */ wined3d_cs_exec_set_predication, - /* WINED3D_CS_OP_SET_VIEWPORT */ wined3d_cs_exec_set_viewport, - /* WINED3D_CS_OP_SET_SCISSOR_RECT */ wined3d_cs_exec_set_scissor_rect, + /* WINED3D_CS_OP_SET_VIEWPORTS */ wined3d_cs_exec_set_viewports, + /* WINED3D_CS_OP_SET_SCISSOR_RECTS */ wined3d_cs_exec_set_scissor_rects, /* WINED3D_CS_OP_SET_RENDERTARGET_VIEW */ wined3d_cs_exec_set_rendertarget_view, /* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW */ wined3d_cs_exec_set_depth_stencil_view, /* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration, @@ -2508,13 +2506,11 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void /* WINED3D_CS_OP_GENERATE_MIPMAPS */ wined3d_cs_exec_generate_mipmaps, }; -#if defined(STAGING_CSMT) static BOOL wined3d_cs_st_check_space(struct wined3d_cs *cs, size_t size, enum wined3d_cs_queue_id queue_id) { return TRUE; } -#endif /* STAGING_CSMT */ static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size, enum wined3d_cs_queue_id queue_id) { if (size > (cs->data_size - cs->end)) @@ -2568,9 +2564,7 @@ static void wined3d_cs_st_finish(struct wined3d_cs *cs, enum wined3d_cs_queue_id static const struct wined3d_cs_ops wined3d_cs_st_ops = { -#if defined(STAGING_CSMT) wined3d_cs_st_check_space, -#endif /* STAGING_CSMT */ wined3d_cs_st_require_space, wined3d_cs_st_submit, wined3d_cs_st_finish, @@ -2607,7 +2601,6 @@ static void wined3d_cs_mt_submit(struct wined3d_cs *cs, enum wined3d_cs_queue_id wined3d_cs_queue_submit(&cs->queue[queue_id], cs); } -#if defined(STAGING_CSMT) static BOOL wined3d_cs_queue_check_space(struct wined3d_cs_queue *queue, size_t size) { size_t queue_size = ARRAY_SIZE(queue->data); @@ -2621,7 +2614,6 @@ static BOOL wined3d_cs_queue_check_space(struct wined3d_cs_queue *queue, size_t return (remaining >= packet_size); } -#endif /* STAGING_CSMT */ static void *wined3d_cs_queue_require_space(struct wined3d_cs_queue *queue, size_t size, struct wined3d_cs *cs) { size_t queue_size = ARRAY_SIZE(queue->data); @@ -2683,7 +2675,6 @@ static void *wined3d_cs_queue_require_space(struct wined3d_cs_queue *queue, size return packet->data; } -#if defined(STAGING_CSMT) static BOOL wined3d_cs_mt_check_space(struct wined3d_cs *cs, size_t size, enum wined3d_cs_queue_id queue_id) { if (cs->thread_id == GetCurrentThreadId()) @@ -2692,7 +2683,6 @@ static BOOL wined3d_cs_mt_check_space(struct wined3d_cs *cs, size_t size, enum w return wined3d_cs_queue_check_space(&cs->queue[queue_id], size); } -#endif /* STAGING_CSMT */ static void *wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, enum wined3d_cs_queue_id queue_id) { if (cs->thread_id == GetCurrentThreadId()) @@ -2715,9 +2705,7 @@ static void wined3d_cs_mt_finish(struct wined3d_cs *cs, enum wined3d_cs_queue_id static const struct wined3d_cs_ops wined3d_cs_mt_ops = { -#if defined(STAGING_CSMT) wined3d_cs_mt_check_space, -#endif /* STAGING_CSMT */ wined3d_cs_mt_require_space, wined3d_cs_mt_submit, wined3d_cs_mt_finish, diff --git a/dll/directx/wine/wined3d/device.c b/dll/directx/wine/wined3d/device.c index e2b27e0cf4..8b4b3f9bb2 100644 --- a/dll/directx/wine/wined3d/device.c +++ b/dll/directx/wine/wined3d/device.c @@ -99,7 +99,7 @@ GLenum gl_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type) } } -static enum wined3d_primitive_type d3d_primitive_type_from_gl(GLenum primitive_type) +enum wined3d_primitive_type d3d_primitive_type_from_gl(GLenum primitive_type) { switch (primitive_type) { @@ -226,11 +226,11 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c float depth, DWORD stencil) { struct wined3d_rendertarget_view *rtv = rt_count ? fb->render_targets[0] : NULL; - struct wined3d_surface *target = rtv ? wined3d_rendertarget_view_get_surface(rtv) : NULL; struct wined3d_rendertarget_view *dsv = fb->depth_stencil; - struct wined3d_surface *depth_stencil = dsv ? wined3d_rendertarget_view_get_surface(dsv) : NULL; const struct wined3d_state *state = &device->cs->state; + struct wined3d_texture *depth_stencil = NULL; const struct wined3d_gl_info *gl_info; + struct wined3d_texture *target = NULL; UINT drawable_width, drawable_height; struct wined3d_color corrected_color; struct wined3d_context *context; @@ -238,10 +238,19 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c BOOL render_offscreen; unsigned int i; - if (target) - context = context_acquire(device, target->container, rtv->sub_resource_idx); + if (rtv && rtv->resource->type != WINED3D_RTYPE_BUFFER) + { + target = texture_from_resource(rtv->resource); + context = context_acquire(device, target, rtv->sub_resource_idx); + } else + { context = context_acquire(device, NULL, 0); + } + + if (dsv && dsv->resource->type != WINED3D_RTYPE_BUFFER) + depth_stencil = texture_from_resource(dsv->resource); + if (!context->valid) { context_release(context); @@ -281,11 +290,11 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c } else { - unsigned int ds_level = dsv->sub_resource_idx % depth_stencil->container->level_count; + unsigned int ds_level = dsv->sub_resource_idx % depth_stencil->level_count; render_offscreen = TRUE; - drawable_width = wined3d_texture_get_level_pow2_width(depth_stencil->container, ds_level); - drawable_height = wined3d_texture_get_level_pow2_height(depth_stencil->container, ds_level); + drawable_width = wined3d_texture_get_level_pow2_width(depth_stencil, ds_level); + drawable_height = wined3d_texture_get_level_pow2_height(depth_stencil, ds_level); } if (depth_stencil) @@ -402,9 +411,7 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c gl_info->gl_ops.gl.p_glScissor(draw_rect->left, drawable_height - draw_rect->bottom, draw_rect->right - draw_rect->left, draw_rect->bottom - draw_rect->top); } - checkGLcall("glScissor"); gl_info->gl_ops.gl.p_glClear(clear_mask); - checkGLcall("glClear"); } else { @@ -439,16 +446,14 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c gl_info->gl_ops.gl.p_glScissor(current_rect.left, drawable_height - current_rect.bottom, current_rect.right - current_rect.left, current_rect.bottom - current_rect.top); } - checkGLcall("glScissor"); - gl_info->gl_ops.gl.p_glClear(clear_mask); - checkGLcall("glClear"); } } + context->scissor_rect_count = WINED3D_MAX_VIEWPORTS; + checkGLcall("clear"); - if (wined3d_settings.strict_draw_ordering || (flags & WINED3DCLEAR_TARGET - && target->container->swapchain && target->container->swapchain->front_buffer == target->container)) - gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ + if (flags & WINED3DCLEAR_TARGET && target->swapchain && target->swapchain->front_buffer == target) + gl_info->gl_ops.gl.p_glFlush(); context_release(context); } @@ -677,12 +682,11 @@ static void create_dummy_textures(struct wined3d_device *device, struct wined3d_ if (gl_info->supported[EXT_TEXTURE_ARRAY]) { - gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_1d_array); TRACE("Dummy 1D array texture given name %u.\n", textures->tex_1d_array); gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D_ARRAY, textures->tex_1d_array); gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, GL_RGBA8, 1, 1, 0, - GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color); + GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color); gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_2d_array); TRACE("Dummy 2D array texture given name %u.\n", textures->tex_2d_array); @@ -752,8 +756,8 @@ static void destroy_dummy_textures(struct wined3d_device *device, struct wined3d if (gl_info->supported[EXT_TEXTURE_ARRAY]) { - gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_1d_array); gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_2d_array); ... 11015 lines suppressed ...
6 years, 7 months
1
0
0
0
01/01: [AMSTREAM] Sync with Wine Staging 3.9. CORE-14656
by Amine Khaldi
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=a5f73f6c864767302bd1b…
commit a5f73f6c864767302bd1b81889f5a691e0ccf501 Author: Amine Khaldi <amine.khaldi(a)reactos.org> AuthorDate: Sun May 27 03:50:07 2018 +0100 Commit: Amine Khaldi <amine.khaldi(a)reactos.org> CommitDate: Sun May 27 03:50:07 2018 +0100 [AMSTREAM] Sync with Wine Staging 3.9. CORE-14656 --- dll/directx/wine/amstream/mediastream.c | 5 ++--- media/doc/README.WINE | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/dll/directx/wine/amstream/mediastream.c b/dll/directx/wine/amstream/mediastream.c index 4c14b631d1..2bad1f3c90 100644 --- a/dll/directx/wine/amstream/mediastream.c +++ b/dll/directx/wine/amstream/mediastream.c @@ -20,7 +20,6 @@ #ifndef __REACTOS__ #define NONAMELESSUNION -#define NONAMELESSSTRUCT #endif #define COBJMACROS @@ -505,7 +504,7 @@ static const IPinVtbl DirectDrawMediaStreamInputPin_IPin_Vtbl = BasePinImpl_QueryPinInfo, BasePinImpl_QueryDirection, BasePinImpl_QueryId, - BaseInputPinImpl_QueryAccept, + BasePinImpl_QueryAccept, BasePinImpl_EnumMediaTypes, BasePinImpl_QueryInternalConnections, BaseInputPinImpl_EndOfStream, @@ -1074,7 +1073,7 @@ static const IPinVtbl AudioMediaStreamInputPin_IPin_Vtbl = BasePinImpl_QueryPinInfo, BasePinImpl_QueryDirection, BasePinImpl_QueryId, - BaseInputPinImpl_QueryAccept, + BasePinImpl_QueryAccept, BasePinImpl_EnumMediaTypes, BasePinImpl_QueryInternalConnections, BaseInputPinImpl_EndOfStream, diff --git a/media/doc/README.WINE b/media/doc/README.WINE index db5c232c42..08e647976b 100644 --- a/media/doc/README.WINE +++ b/media/doc/README.WINE @@ -21,7 +21,7 @@ reactos/sdk/tools/wpp # Synced to WineStaging-2.9 The following libraries are shared with Wine. -reactos/dll/directx/wine/amstream # Synced to WineStaging-3.3 +reactos/dll/directx/wine/amstream # Synced to WineStaging-3.9 reactos/dll/directx/wine/d3d8 # Synced to WineStaging-3.3 reactos/dll/directx/wine/d3d9 # Synced to WineStaging-3.3 reactos/dll/directx/wine/d3dcompiler_43 # Synced to WineStaging-3.3
6 years, 7 months
1
0
0
0
01/01: [REG_WINETEST] Sync with Wine Staging 3.9. CORE-14656
by Amine Khaldi
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=fcf9cc1ab731d62f2a628…
commit fcf9cc1ab731d62f2a628690172f35f3b43d979c Author: Amine Khaldi <amine.khaldi(a)reactos.org> AuthorDate: Sun May 27 03:49:14 2018 +0100 Commit: Amine Khaldi <amine.khaldi(a)reactos.org> CommitDate: Sun May 27 03:49:14 2018 +0100 [REG_WINETEST] Sync with Wine Staging 3.9. CORE-14656 --- modules/rostests/winetests/reg/reg.c | 88 +++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 2 deletions(-) diff --git a/modules/rostests/winetests/reg/reg.c b/modules/rostests/winetests/reg/reg.c index b64defb48d..ea4e128da5 100644 --- a/modules/rostests/winetests/reg/reg.c +++ b/modules/rostests/winetests/reg/reg.c @@ -2355,6 +2355,23 @@ static void test_import(void) verify_reg(hkey, "Wine68h", REG_BINARY, NULL, 0, 0); verify_reg(hkey, "Wine68i", REG_NONE, NULL, 0, 0); + /* Test with embedded null characters */ + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine69a\"=\"\\0\n" + "\"Wine69b\"=\"\\0\\0\n" + "\"Wine69c\"=\"Value1\\0\n" + "\"Wine69d\"=\"Value2\\0\\0\\0\\0\n" + "\"Wine69e\"=\"Value3\\0Value4\n" + "\"Wine69f\"=\"\\0Value4\n\n", &r); + ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + verify_reg_nonexist(hkey, "Wine69a"); + verify_reg_nonexist(hkey, "Wine69b"); + verify_reg_nonexist(hkey, "Wine69c"); + verify_reg_nonexist(hkey, "Wine69d"); + verify_reg_nonexist(hkey, "Wine69e"); + verify_reg_nonexist(hkey, "Wine69f"); + err = RegCloseKey(hkey); ok(err == ERROR_SUCCESS, "got %d, expected 0\n", err); @@ -3863,6 +3880,23 @@ static void test_unicode_import(void) verify_reg(hkey, "Wine68h", REG_BINARY, NULL, 0, 0); verify_reg(hkey, "Wine68i", REG_NONE, NULL, 0, 0); + /* Test with embedded null characters */ + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine69a\"=\"\\0\n" + "\"Wine69b\"=\"\\0\\0\n" + "\"Wine69c\"=\"Value1\\0\n" + "\"Wine69d\"=\"Value2\\0\\0\\0\\0\n" + "\"Wine69e\"=\"Value3\\0Value4\n" + "\"Wine69f\"=\"\\0Value4\n\n", &r); + ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + verify_reg_nonexist(hkey, "Wine69a"); + verify_reg_nonexist(hkey, "Wine69b"); + verify_reg_nonexist(hkey, "Wine69c"); + verify_reg_nonexist(hkey, "Wine69d"); + verify_reg_nonexist(hkey, "Wine69e"); + verify_reg_nonexist(hkey, "Wine69f"); + err = RegCloseKey(hkey); ok(err == ERROR_SUCCESS, "got %d, expected 0\n", err); @@ -4328,9 +4362,9 @@ error: static void test_export(void) { LONG err; - DWORD r, dword; + DWORD r, dword, type, size; HKEY hkey, subkey; - BYTE hex[4]; + BYTE hex[4], buffer[8]; const char *empty_key_test = "\xef\xbb\xbfWindows Registry Editor Version 5.00\r\n\r\n" @@ -4406,6 +4440,18 @@ static void test_export(void) "\"Wine3b\"=hex:12,34,56,78\r\n" "\"Wine3c\"=dword:10203040\r\n\r\n"; + const char *embedded_null_test = + "\xef\xbb\xbfWindows Registry Editor Version 5.00\r\n\r\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\r\n" + "\"Wine4a\"=dword:00000005\r\n" + "\"Wine4b\"=\"\"\r\n" + "\"Wine4c\"=\"Value\"\r\n" + "\"Wine4d\"=\"\"\r\n" + "\"Wine4e\"=dword:00000100\r\n" + "\"Wine4f\"=\"\"\r\n" + "\"Wine4g\"=\"Value2\"\r\n" + "\"Wine4h\"=\"abc\"\r\n\r\n"; + err = RegDeleteKeyA(HKEY_CURRENT_USER, KEY_BASE); ok(err == ERROR_SUCCESS || err == ERROR_FILE_NOT_FOUND, "got %d\n", err); @@ -4598,6 +4644,44 @@ static void test_export(void) ok(compare_export("file.reg", hex_types_test, 0), "compare_export() failed\n"); delete_key(HKEY_CURRENT_USER, KEY_BASE); + + /* Test registry export with embedded null characters */ + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine4a\"=dword:00000005\n" + "\"Wine4b\"=hex(1):00,00,00,00,00,00,00,00\n" + "\"Wine4c\"=\"Value\"\n" + "\"Wine4d\"=hex(1):00,00,61,00,62,00,63,00\n" + "\"Wine4e\"=dword:00000100\n" + "\"Wine4f\"=hex(1):00,00,56,00,61,00,6c,00,75,00,65,00,00,00\n" + "\"Wine4g\"=\"Value2\"\n" + "\"Wine4h\"=hex(1):61,00,62,00,63,00,00,00, \\\n" + " 64,00,65,00,66,00,00,00\n\n", &r); + ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + open_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey); + dword = 0x5; + verify_reg(hkey, "Wine4a", REG_DWORD, &dword, sizeof(dword), 0); + verify_reg(hkey, "Wine4b", REG_SZ, "\0\0\0\0\0\0\0", 4, 0); + verify_reg(hkey, "Wine4c", REG_SZ, "Value", 6, 0); + /* Wine4d */ + size = sizeof(buffer); + err = RegQueryValueExA(hkey, "Wine4d", NULL, &type, (BYTE *)&buffer, &size); + ok(err == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", err); + ok(type == REG_SZ, "got wrong type %u, expected %u\n", type, REG_SZ); + ok(size == 5 || broken(size == 4) /* WinXP */, "got wrong size %u, expected 5\n", size); + ok(memcmp(buffer, "\0abc", size) == 0, "got wrong data\n"); + dword = 0x100; + verify_reg(hkey, "Wine4e", REG_DWORD, &dword, sizeof(dword), 0); + verify_reg(hkey, "Wine4f", REG_SZ, "\0Value", 7, 0); + verify_reg(hkey, "Wine4g", REG_SZ, "Value2", 7, 0); + verify_reg(hkey, "Wine4h", REG_SZ, "abc\0def", 8, 0); + RegCloseKey(hkey); + + run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg", &r); + ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + ok(compare_export("file.reg", embedded_null_test, 0), "compare_export() failed\n"); + + delete_key(HKEY_CURRENT_USER, KEY_BASE); } START_TEST(reg)
6 years, 7 months
1
0
0
0
01/01: [REG] Sync with Wine Staging 3.9. CORE-14656
by Amine Khaldi
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=98cf80fbc5aee64b25271…
commit 98cf80fbc5aee64b2527170f270da683a22640a6 Author: Amine Khaldi <amine.khaldi(a)reactos.org> AuthorDate: Sun May 27 03:48:33 2018 +0100 Commit: Amine Khaldi <amine.khaldi(a)reactos.org> CommitDate: Sun May 27 03:48:33 2018 +0100 [REG] Sync with Wine Staging 3.9. CORE-14656 --- base/applications/cmdutils/reg/export.c | 11 ++++++----- base/applications/cmdutils/reg/import.c | 3 ++- media/doc/README.WINE | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/base/applications/cmdutils/reg/export.c b/base/applications/cmdutils/reg/export.c index 622e7ca8d9..8b08da1299 100644 --- a/base/applications/cmdutils/reg/export.c +++ b/base/applications/cmdutils/reg/export.c @@ -39,7 +39,10 @@ static WCHAR *escape_string(WCHAR *str, size_t str_len, size_t *line_len) for (i = 0, escape_count = 0; i < str_len; i++) { WCHAR c = str[i]; - if (c == '\r' || c == '\n' || c == '\\' || c == '"' || c == '\0') + + if (!c) break; + + if (c == '\r' || c == '\n' || c == '\\' || c == '"') escape_count++; } @@ -49,6 +52,8 @@ static WCHAR *escape_string(WCHAR *str, size_t str_len, size_t *line_len) { WCHAR c = str[i]; + if (!c) break; + switch (c) { case '\r': @@ -67,10 +72,6 @@ static WCHAR *escape_string(WCHAR *str, size_t str_len, size_t *line_len) buf[pos++] = '\\'; buf[pos] = '"'; break; - case '\0': - buf[pos++] = '\\'; - buf[pos] = '0'; - break; default: buf[pos] = c; } diff --git a/base/applications/cmdutils/reg/import.c b/base/applications/cmdutils/reg/import.c index f2ce80e7cb..779ea2863b 100644 --- a/base/applications/cmdutils/reg/import.c +++ b/base/applications/cmdutils/reg/import.c @@ -409,7 +409,8 @@ static void free_parser_data(struct parser *parser) static void prepare_hex_string_data(struct parser *parser) { - if (parser->data_type == REG_EXPAND_SZ || parser->data_type == REG_MULTI_SZ) + if (parser->data_type == REG_EXPAND_SZ || parser->data_type == REG_MULTI_SZ || + parser->data_type == REG_SZ) { if (parser->is_unicode) { diff --git a/media/doc/README.WINE b/media/doc/README.WINE index 6dc5502c87..db5c232c42 100644 --- a/media/doc/README.WINE +++ b/media/doc/README.WINE @@ -227,7 +227,7 @@ reactos/win32ss/printing/monitors/localmon/ui/ # Synced to WineStaging-3.3 (kno ReactOS shares the following programs with Winehq. reactos/base/applications/cmdutils/cscript # Synced to WineStaging-3.3 -reactos/base/applications/cmdutils/reg # Synced to WineStaging-3.3 +reactos/base/applications/cmdutils/reg # Synced to WineStaging-3.9 reactos/base/applications/cmdutils/schtasks # Synced to WineStaging-3.3 reactos/base/applications/cmdutils/taskkill # Synced to WineStaging-3.3 reactos/base/applications/cmdutils/wmic # Synced to WineStaging-3.3
6 years, 7 months
1
0
0
0
04/04: [USETUP] Similarly to what was done for GenLists, factor out the UI code from the partition list code.
by Hermès Bélusca-Maïto
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=216f15c675ec17382f13b…
commit 216f15c675ec17382f13b913577d156d664cbc19 Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org> AuthorDate: Mon May 15 19:41:18 2017 +0000 Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org> CommitDate: Sat May 26 22:45:50 2018 +0200 [USETUP] Similarly to what was done for GenLists, factor out the UI code from the partition list code. This will allow to reuse it for the 1st-stage GUI setup too, while using another UI representation. Add also two partition iterator functions: GetNextPartition and GetPrevPartition. svn path=/branches/setup_improvements/; revision=74554 --- base/setup/usetup/partlist.c | 252 ++++++++++++++++++++++++------------------- base/setup/usetup/partlist.h | 72 +++++++++---- base/setup/usetup/usetup.c | 54 ++++------ 3 files changed, 208 insertions(+), 170 deletions(-) diff --git a/base/setup/usetup/partlist.c b/base/setup/usetup/partlist.c index 7d52208bad..31c657f702 100644 --- a/base/setup/usetup/partlist.c +++ b/base/setup/usetup/partlist.c @@ -1419,11 +1419,7 @@ AddDiskToList( PPARTLIST -CreatePartitionList( - SHORT Left, - SHORT Top, - SHORT Right, - SHORT Bottom) +CreatePartitionList(VOID) { PPARTLIST List; OBJECT_ATTRIBUTES ObjectAttributes; @@ -1442,14 +1438,6 @@ CreatePartitionList( if (List == NULL) return NULL; - List->Left = Left; - List->Top = Top; - List->Right = Right; - List->Bottom = Bottom; - - List->Line = 0; - List->Offset = 0; - List->CurrentDisk = NULL; List->CurrentPartition = NULL; @@ -1466,10 +1454,11 @@ CreatePartitionList( Status = NtQuerySystemInformation(SystemDeviceInformation, &Sdi, - sizeof(SYSTEM_DEVICE_INFORMATION), + sizeof(Sdi), &ReturnSize); if (!NT_SUCCESS(Status)) { + DPRINT1("NtQuerySystemInformation() failed, Status 0x%08lx", Status); RtlFreeHeap(ProcessHeap, 0, List); return NULL; } @@ -1593,23 +1582,47 @@ DestroyPartitionList( } +VOID +InitPartitionListUi( + IN OUT PPARTLIST_UI ListUi, + IN PPARTLIST List, + IN SHORT Left, + IN SHORT Top, + IN SHORT Right, + IN SHORT Bottom) +{ + ListUi->List = List; + // ListUi->FirstShown = NULL; + // ListUi->LastShown = NULL; + + ListUi->Left = Left; + ListUi->Top = Top; + ListUi->Right = Right; + ListUi->Bottom = Bottom; + + ListUi->Line = 0; + ListUi->Offset = 0; + + // ListUi->Redraw = TRUE; +} + static VOID PrintEmptyLine( - IN PPARTLIST List) + IN PPARTLIST_UI ListUi) { COORD coPos; ULONG Written; USHORT Width; USHORT Height; - Width = List->Right - List->Left - 1; - Height = List->Bottom - List->Top - 2; + Width = ListUi->Right - ListUi->Left - 1; + Height = ListUi->Bottom - ListUi->Top - 2; - coPos.X = List->Left + 1; - coPos.Y = List->Top + 1 + List->Line; + coPos.X = ListUi->Left + 1; + coPos.Y = ListUi->Top + 1 + ListUi->Line; - if (List->Line >= 0 && List->Line <= Height) + if (ListUi->Line >= 0 && ListUi->Line <= Height) { FillConsoleOutputAttribute(StdOutput, FOREGROUND_WHITE | BACKGROUND_BLUE, @@ -1624,17 +1637,18 @@ PrintEmptyLine( &Written); } - List->Line++; + ListUi->Line++; } static VOID PrintPartitionData( - IN PPARTLIST List, + IN PPARTLIST_UI ListUi, IN PDISKENTRY DiskEntry, IN PPARTENTRY PartEntry) { + PPARTLIST List = ListUi->List; CHAR LineBuffer[128]; COORD coPos; ULONG Written; @@ -1644,14 +1658,13 @@ PrintPartitionData( PCHAR Unit; UCHAR Attribute; CHAR PartTypeString[32]; - PCHAR PartType; - PartType = PartTypeString; + PCHAR PartType = PartTypeString; - Width = List->Right - List->Left - 1; - Height = List->Bottom - List->Top - 2; + Width = ListUi->Right - ListUi->Left - 1; + Height = ListUi->Bottom - ListUi->Top - 2; - coPos.X = List->Left + 1; - coPos.Y = List->Top + 1 + List->Line; + coPos.X = ListUi->Left + 1; + coPos.Y = ListUi->Top + 1 + ListUi->Line; if (PartEntry->IsPartitioned == FALSE) { @@ -1751,7 +1764,7 @@ PrintPartitionData( FOREGROUND_BLUE | BACKGROUND_WHITE : FOREGROUND_WHITE | BACKGROUND_BLUE; - if (List->Line >= 0 && List->Line <= Height) + if (ListUi->Line >= 0 && ListUi->Line <= Height) { FillConsoleOutputCharacterA(StdOutput, ' ', @@ -1761,7 +1774,7 @@ PrintPartitionData( } coPos.X += 4; Width -= 8; - if (List->Line >= 0 && List->Line <= Height) + if (ListUi->Line >= 0 && ListUi->Line <= Height) { FillConsoleOutputAttribute(StdOutput, Attribute, @@ -1771,7 +1784,7 @@ PrintPartitionData( } coPos.X++; Width -= 2; - if (List->Line >= 0 && List->Line <= Height) + if (ListUi->Line >= 0 && ListUi->Line <= Height) { WriteConsoleOutputCharacterA(StdOutput, LineBuffer, @@ -1780,16 +1793,17 @@ PrintPartitionData( &Written); } - List->Line++; + ListUi->Line++; } static VOID PrintDiskData( - IN PPARTLIST List, + IN PPARTLIST_UI ListUi, IN PDISKENTRY DiskEntry) { + // PPARTLIST List = ListUi->List; PPARTENTRY PrimaryPartEntry, LogicalPartEntry; PLIST_ENTRY PrimaryEntry, LogicalEntry; CHAR LineBuffer[128]; @@ -1800,11 +1814,11 @@ PrintDiskData( ULARGE_INTEGER DiskSize; PCHAR Unit; - Width = List->Right - List->Left - 1; - Height = List->Bottom - List->Top - 2; + Width = ListUi->Right - ListUi->Left - 1; + Height = ListUi->Bottom - ListUi->Top - 2; - coPos.X = List->Left + 1; - coPos.Y = List->Top + 1 + List->Line; + coPos.X = ListUi->Left + 1; + coPos.Y = ListUi->Top + 1 + ListUi->Line; DiskSize.QuadPart = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector; if (DiskSize.QuadPart >= 10737418240) /* 10 GB */ @@ -1844,7 +1858,7 @@ PrintDiskData( DiskEntry->Id); } - if (List->Line >= 0 && List->Line <= Height) + if (ListUi->Line >= 0 && ListUi->Line <= Height) { FillConsoleOutputAttribute(StdOutput, FOREGROUND_WHITE | BACKGROUND_BLUE, @@ -1860,7 +1874,7 @@ PrintDiskData( } coPos.X++; - if (List->Line >= 0 && List->Line <= Height) + if (ListUi->Line >= 0 && ListUi->Line <= Height) { WriteConsoleOutputCharacterA(StdOutput, LineBuffer, @@ -1869,10 +1883,10 @@ PrintDiskData( &Written); } - List->Line++; + ListUi->Line++; /* Print separator line */ - PrintEmptyLine(List); + PrintEmptyLine(ListUi); /* Print partition lines */ PrimaryEntry = DiskEntry->PrimaryPartListHead.Flink; @@ -1880,7 +1894,7 @@ PrintDiskData( { PrimaryPartEntry = CONTAINING_RECORD(PrimaryEntry, PARTENTRY, ListEntry); - PrintPartitionData(List, + PrintPartitionData(ListUi, DiskEntry, PrimaryPartEntry); @@ -1891,7 +1905,7 @@ PrintDiskData( { LogicalPartEntry = CONTAINING_RECORD(LogicalEntry, PARTENTRY, ListEntry); - PrintPartitionData(List, + PrintPartitionData(ListUi, DiskEntry, LogicalPartEntry); @@ -1903,14 +1917,15 @@ PrintDiskData( } /* Print separator line */ - PrintEmptyLine(List); + PrintEmptyLine(ListUi); } VOID DrawPartitionList( - IN PPARTLIST List) + IN PPARTLIST_UI ListUi) { + PPARTLIST List = ListUi->List; PLIST_ENTRY Entry, Entry2; PDISKENTRY DiskEntry; PPARTENTRY PartEntry = NULL; @@ -2001,37 +2016,37 @@ DrawPartitionList( } /* If it possible, make the disk name visible */ - if (CurrentPartLine < List->Offset) + if (CurrentPartLine < ListUi->Offset) { - List->Offset = CurrentPartLine; + ListUi->Offset = CurrentPartLine; } - else if (CurrentPartLine - List->Offset > List->Bottom - List->Top - 2) + else if (CurrentPartLine - ListUi->Offset > ListUi->Bottom - ListUi->Top - 2) { - List->Offset = CurrentPartLine - (List->Bottom - List->Top - 2); + ListUi->Offset = CurrentPartLine - (ListUi->Bottom - ListUi->Top - 2); } - if (CurrentDiskLine < List->Offset && CurrentPartLine - CurrentDiskLine < List->Bottom - List->Top - 2) + if (CurrentDiskLine < ListUi->Offset && CurrentPartLine - CurrentDiskLine < ListUi->Bottom - ListUi->Top - 2) { - List->Offset = CurrentDiskLine; + ListUi->Offset = CurrentDiskLine; } - /* draw upper left corner */ - coPos.X = List->Left; - coPos.Y = List->Top; + /* Draw upper left corner */ + coPos.X = ListUi->Left; + coPos.Y = ListUi->Top; FillConsoleOutputCharacterA(StdOutput, 0xDA, // '+', 1, coPos, &Written); - /* draw upper edge */ - coPos.X = List->Left + 1; - coPos.Y = List->Top; - if (List->Offset == 0) + /* Draw upper edge */ + coPos.X = ListUi->Left + 1; + coPos.Y = ListUi->Top; + if (ListUi->Offset == 0) { FillConsoleOutputCharacterA(StdOutput, 0xC4, // '-', - List->Right - List->Left - 1, + ListUi->Right - ListUi->Left - 1, coPos, &Written); } @@ -2039,16 +2054,16 @@ DrawPartitionList( { FillConsoleOutputCharacterA(StdOutput, 0xC4, // '-', - List->Right - List->Left - 5, + ListUi->Right - ListUi->Left - 5, coPos, &Written); - coPos.X = List->Right - 5; + coPos.X = ListUi->Right - 5; WriteConsoleOutputCharacterA(StdOutput, "(\x18)", // "(up)" 3, coPos, &Written); - coPos.X = List->Right - 2; + coPos.X = ListUi->Right - 2; FillConsoleOutputCharacterA(StdOutput, 0xC4, // '-', 2, @@ -2056,19 +2071,19 @@ DrawPartitionList( &Written); } - /* draw upper right corner */ - coPos.X = List->Right; - coPos.Y = List->Top; + /* Draw upper right corner */ + coPos.X = ListUi->Right; + coPos.Y = ListUi->Top; FillConsoleOutputCharacterA(StdOutput, 0xBF, // '+', 1, coPos, &Written); - /* draw left and right edge */ - for (i = List->Top + 1; i < List->Bottom; i++) + /* Draw left and right edge */ + for (i = ListUi->Top + 1; i < ListUi->Bottom; i++) { - coPos.X = List->Left; + coPos.X = ListUi->Left; coPos.Y = i; FillConsoleOutputCharacterA(StdOutput, 0xB3, // '|', @@ -2076,7 +2091,7 @@ DrawPartitionList( coPos, &Written); - coPos.X = List->Right; + coPos.X = ListUi->Right; FillConsoleOutputCharacterA(StdOutput, 0xB3, //'|', 1, @@ -2084,23 +2099,23 @@ DrawPartitionList( &Written); } - /* draw lower left corner */ - coPos.X = List->Left; - coPos.Y = List->Bottom; + /* Draw lower left corner */ + coPos.X = ListUi->Left; + coPos.Y = ListUi->Bottom; FillConsoleOutputCharacterA(StdOutput, 0xC0, // '+', 1, coPos, &Written); - /* draw lower edge */ - coPos.X = List->Left + 1; - coPos.Y = List->Bottom; - if (LastLine - List->Offset <= List->Bottom - List->Top - 2) + /* Draw lower edge */ + coPos.X = ListUi->Left + 1; + coPos.Y = ListUi->Bottom; + if (LastLine - ListUi->Offset <= ListUi->Bottom - ListUi->Top - 2) { FillConsoleOutputCharacterA(StdOutput, 0xC4, // '-', - List->Right - List->Left - 1, + ListUi->Right - ListUi->Left - 1, coPos, &Written); } @@ -2108,16 +2123,16 @@ DrawPartitionList( { FillConsoleOutputCharacterA(StdOutput, 0xC4, // '-', - List->Right - List->Left - 5, + ListUi->Right - ListUi->Left - 5, coPos, &Written); - coPos.X = List->Right - 5; + coPos.X = ListUi->Right - 5; WriteConsoleOutputCharacterA(StdOutput, "(\x19)", // "(down)" 3, coPos, &Written); - coPos.X = List->Right - 2; + coPos.X = ListUi->Right - 2; FillConsoleOutputCharacterA(StdOutput, 0xC4, // '-', 2, @@ -2125,9 +2140,9 @@ DrawPartitionList( &Written); } - /* draw lower right corner */ - coPos.X = List->Right; - coPos.Y = List->Bottom; + /* Draw lower right corner */ + coPos.X = ListUi->Right; + coPos.Y = ListUi->Bottom; FillConsoleOutputCharacterA(StdOutput, 0xD9, // '+', 1, @@ -2135,7 +2150,7 @@ DrawPartitionList( &Written); /* print list entries */ - List->Line = - List->Offset; + ListUi->Line = - ListUi->Offset; Entry = List->DiskListHead.Flink; while (Entry != &List->DiskListHead) @@ -2143,8 +2158,7 @@ DrawPartitionList( DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry); /* Print disk entry */ - PrintDiskData(List, - DiskEntry); + PrintDiskData(ListUi, DiskEntry); Entry = Entry->Flink; } @@ -2159,8 +2173,7 @@ SelectPartition( { PDISKENTRY DiskEntry; PPARTENTRY PartEntry; - PLIST_ENTRY Entry1; - PLIST_ENTRY Entry2; + PLIST_ENTRY Entry1, Entry2; /* Check for empty disks */ if (IsListEmpty(&List->DiskListHead)) @@ -2181,10 +2194,9 @@ SelectPartition( if (PartEntry->PartitionNumber == PartitionNumber) { - List->CurrentDisk = DiskEntry; - List->CurrentPartition = PartEntry; - DrawPartitionList(List); - return TRUE; + List->CurrentDisk = DiskEntry; + List->CurrentPartition = PartEntry; + return TRUE; } Entry2 = Entry2->Flink; @@ -2200,8 +2212,8 @@ SelectPartition( } -BOOL -ScrollDownPartitionList( +PPARTENTRY +GetNextPartition( IN PPARTLIST List) { PLIST_ENTRY DiskListEntry; @@ -2211,7 +2223,7 @@ ScrollDownPartitionList( /* Fail, if no disks are available */ if (IsListEmpty(&List->DiskListHead)) - return FALSE; + return NULL; /* Check for next usable entry on current disk */ if (List->CurrentPartition != NULL) @@ -2227,7 +2239,7 @@ ScrollDownPartitionList( PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry); List->CurrentPartition = PartEntry; - return TRUE; + return List->CurrentPartition; } else { @@ -2237,7 +2249,7 @@ ScrollDownPartitionList( PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry); List->CurrentPartition = PartEntry; - return TRUE; + return List->CurrentPartition; } } } @@ -2255,7 +2267,7 @@ ScrollDownPartitionList( PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry); List->CurrentPartition = PartEntry; - return TRUE; + return List->CurrentPartition; } } else @@ -2267,7 +2279,7 @@ ScrollDownPartitionList( PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry); List->CurrentPartition = PartEntry; - return TRUE; + return List->CurrentPartition; } } } @@ -2286,18 +2298,17 @@ ScrollDownPartitionList( List->CurrentDisk = DiskEntry; List->CurrentPartition = PartEntry; - return TRUE; + return List->CurrentPartition; } DiskListEntry = DiskListEntry->Flink; } - return FALSE; + return NULL; } - -BOOL -ScrollUpPartitionList( +PPARTENTRY +GetPrevPartition( IN PPARTLIST List) { PLIST_ENTRY DiskListEntry; @@ -2307,7 +2318,7 @@ ScrollUpPartitionList( /* Fail, if no disks are available */ if (IsListEmpty(&List->DiskListHead)) - return FALSE; + return NULL; /* Check for previous usable entry on current disk */ if (List->CurrentPartition != NULL) @@ -2323,12 +2334,12 @@ ScrollUpPartitionList( } else { - /* Extended partition*/ + /* Extended partition */ PartEntry = List->CurrentDisk->ExtendedPartition; } List->CurrentPartition = PartEntry; - return TRUE; + return List->CurrentPartition; } else { @@ -2347,9 +2358,8 @@ ScrollUpPartitionList( } List->CurrentPartition = PartEntry; - return TRUE; + return List->CurrentPartition; } - } } @@ -2374,21 +2384,39 @@ ScrollUpPartitionList( List->CurrentDisk = DiskEntry; List->CurrentPartition = PartEntry; - return TRUE; + return List->CurrentPartition; } } else { List->CurrentDisk = DiskEntry; List->CurrentPartition = PartEntry; - return TRUE; + return List->CurrentPartition; } } DiskListEntry = DiskListEntry->Blink; } - return FALSE; + return NULL; +} + + + +VOID +ScrollDownPartitionList( + IN PPARTLIST_UI ListUi) +{ + if (GetNextPartition(ListUi->List)) + DrawPartitionList(ListUi); +} + +VOID +ScrollUpPartitionList( + IN PPARTLIST_UI ListUi) +{ + if (GetPrevPartition(ListUi->List)) + DrawPartitionList(ListUi); } diff --git a/base/setup/usetup/partlist.h b/base/setup/usetup/partlist.h index 35c83b3f17..e434959437 100644 --- a/base/setup/usetup/partlist.h +++ b/base/setup/usetup/partlist.h @@ -150,16 +150,9 @@ typedef struct _DISKENTRY typedef struct _PARTLIST { - /* UI stuff */ - SHORT Left; - SHORT Top; - SHORT Right; - SHORT Bottom; - - SHORT Line; - SHORT Offset; - /* + * Disk & Partition iterators. + * * NOTE that when CurrentPartition != NULL, then CurrentPartition->DiskEntry * must be the same as CurrentDisk. We should however keep the two members * separated as we can have a current (selected) disk without any current @@ -237,32 +230,24 @@ GetPartTypeStringFromPartitionType( IN ULONG cchPartType); PPARTLIST -CreatePartitionList( - SHORT Left, - SHORT Top, - SHORT Right, - SHORT Bottom); +CreatePartitionList(VOID); VOID DestroyPartitionList( IN PPARTLIST List); -VOID -DrawPartitionList( - IN PPARTLIST List); - ULONG SelectPartition( IN PPARTLIST List, IN ULONG DiskNumber, IN ULONG PartitionNumber); -BOOL -ScrollDownPartitionList( +PPARTENTRY +GetNextPartition( IN PPARTLIST List); -BOOL -ScrollUpPartitionList( +PPARTENTRY +GetPrevPartition( IN PPARTLIST List); VOID @@ -328,4 +313,47 @@ GetNextUncheckedPartition( OUT PDISKENTRY *pDiskEntry OPTIONAL, OUT PPARTENTRY *pPartEntry); + + + + +typedef struct _PARTLIST_UI +{ + PPARTLIST List; + + // PLIST_ENTRY FirstShown; + // PLIST_ENTRY LastShown; + + SHORT Left; + SHORT Top; + SHORT Right; + SHORT Bottom; + + SHORT Line; + SHORT Offset; + + // BOOL Redraw; +} PARTLIST_UI, *PPARTLIST_UI; + +VOID +InitPartitionListUi( + IN OUT PPARTLIST_UI ListUi, + IN PPARTLIST List, + IN SHORT Left, + IN SHORT Top, + IN SHORT Right, + IN SHORT Bottom); + +VOID +ScrollDownPartitionList( + IN PPARTLIST_UI ListUi); + +VOID +ScrollUpPartitionList( + IN PPARTLIST_UI ListUi); + +VOID +DrawPartitionList( + IN PPARTLIST_UI ListUi); + /* EOF */ diff --git a/base/setup/usetup/usetup.c b/base/setup/usetup/usetup.c index 49f3af72cc..ff2e80b6c1 100644 --- a/base/setup/usetup/usetup.c +++ b/base/setup/usetup/usetup.c @@ -790,39 +790,16 @@ LanguagePage(PINPUT_RECORD Ir) static PAGE_NUMBER SetupStartPage(PINPUT_RECORD Ir) { - //SYSTEM_DEVICE_INFORMATION Sdi; NTSTATUS Status; WCHAR FileNameBuffer[MAX_PATH]; INFCONTEXT Context; PWCHAR Value; UINT ErrorLine; - //ULONG ReturnSize; PGENERIC_LIST_ENTRY ListEntry; INT IntValue; CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT)); -#if 0 - /* Check whether a harddisk is available */ - Status = NtQuerySystemInformation(SystemDeviceInformation, - &Sdi, - sizeof(SYSTEM_DEVICE_INFORMATION), - &ReturnSize); - - if (!NT_SUCCESS(Status)) - { - CONSOLE_PrintTextXY(6, 15, "NtQuerySystemInformation() failed (Status 0x%08lx)", Status); - MUIDisplayError(ERROR_DRIVE_INFORMATION, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; - } - - if (Sdi.NumberOfDisks == 0) - { - MUIDisplayError(ERROR_NO_HDD, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; - } -#endif - /* Get the source path and source root path */ Status = GetSourcePaths(&SourcePath, &SourceRootPath, @@ -896,7 +873,7 @@ SetupStartPage(PINPUT_RECORD Ir) RequiredPartitionDiskSpace = (ULONG)IntValue; - /* Start PnP thread */ + /* Start the PnP thread */ if (hPnpThread != INVALID_HANDLE_VALUE) { NtResumeThread(hPnpThread, NULL); @@ -907,8 +884,7 @@ SetupStartPage(PINPUT_RECORD Ir) if (IsUnattendedSetup) { - //TODO - //read options from inf + // TODO: Read options from inf ComputerList = CreateComputerTypeList(SetupInf); DisplayList = CreateDisplayDriverList(SetupInf); KeyboardList = CreateKeyboardDriverList(SetupInf); @@ -993,7 +969,7 @@ IntroPage(PINPUT_RECORD Ir) { return REPAIR_INTRO_PAGE; } - else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'L') /* R */ + else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'L') /* L */ { return LICENSE_PAGE; } @@ -1533,19 +1509,18 @@ IsDiskSizeValid(PPARTENTRY PartEntry) static PAGE_NUMBER SelectPartitionPage(PINPUT_RECORD Ir) { + PARTLIST_UI ListUi; ULONG Error; MUIDisplayPage(SELECT_PARTITION_PAGE); if (PartitionList == NULL) { - PartitionList = CreatePartitionList(2, - 23, - xScreen - 3, - yScreen - 3); + PartitionList = CreatePartitionList(); if (PartitionList == NULL) { /* FIXME: show an error dialog */ + MUIDisplayError(ERROR_DRIVE_INFORMATION, Ir, POPUP_WAIT_ENTER); return QUIT_PAGE; } else if (IsListEmpty(&PartitionList->DiskListHead)) @@ -1555,7 +1530,12 @@ SelectPartitionPage(PINPUT_RECORD Ir) } } - DrawPartitionList(PartitionList); + InitPartitionListUi(&ListUi, PartitionList, + 2, + 23, + xScreen - 3, + yScreen - 3); + DrawPartitionList(&ListUi); if (IsUnattendedSetup) { @@ -1576,6 +1556,7 @@ SelectPartitionPage(PINPUT_RECORD Ir) TRUE); } +// FIXME?? Aren't we going to enter an infinite loop, if this test fails?? if (!IsDiskSizeValid(PartitionList->CurrentPartition)) { MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE, Ir, POPUP_WAIT_ANY_KEY, @@ -1590,6 +1571,9 @@ SelectPartitionPage(PINPUT_RECORD Ir) } else { + DrawPartitionList(&ListUi); + +// FIXME?? Aren't we going to enter an infinite loop, if this test fails?? if (!IsDiskSizeValid(PartitionList->CurrentPartition)) { MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE, Ir, POPUP_WAIT_ANY_KEY, @@ -1657,14 +1641,12 @@ SelectPartitionPage(PINPUT_RECORD Ir) else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */ { - if (ScrollDownPartitionList(PartitionList)) - DrawPartitionList(PartitionList); + ScrollDownPartitionList(&ListUi); } else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */ { - if (ScrollUpPartitionList(PartitionList)) - DrawPartitionList(PartitionList); + ScrollUpPartitionList(&ListUi); } else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */ {
6 years, 7 months
1
0
0
0
← Newer
1
...
4
5
6
7
8
9
10
...
22
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Results per page:
10
25
50
100
200