Wine-devel
Threads by month
- ----- 2026 -----
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
March 2020
- 72 participants
- 969 discussions
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
dlls/qasf/Makefile.in | 3 +-
dlls/qasf/qasf_classes.idl | 7 ++
dlls/qasf/qasf_main.c | 3 +
dlls/qasf/qasf_private.h | 1 +
dlls/qasf/tests/Makefile.in | 3 +-
dlls/qasf/tests/wmasf.c | 182 ++++++++++++++++++++++++++++++++++++
dlls/qasf/wmasf.c | 67 +++++++++++++
7 files changed, 264 insertions(+), 2 deletions(-)
create mode 100644 dlls/qasf/tests/wmasf.c
create mode 100644 dlls/qasf/wmasf.c
diff --git a/dlls/qasf/Makefile.in b/dlls/qasf/Makefile.in
index dd02f5a344..d7e0168fab 100644
--- a/dlls/qasf/Makefile.in
+++ b/dlls/qasf/Makefile.in
@@ -5,7 +5,8 @@ EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \
dmowrapper.c \
- qasf_main.c
+ qasf_main.c \
+ wmasf.c
IDL_SRCS = \
qasf_classes.idl
diff --git a/dlls/qasf/qasf_classes.idl b/dlls/qasf/qasf_classes.idl
index 0acf380691..b6f6c58fed 100644
--- a/dlls/qasf/qasf_classes.idl
+++ b/dlls/qasf/qasf_classes.idl
@@ -25,3 +25,10 @@
uuid(94297043-bd82-4dfd-b0de-8177739c6d20),
]
coclass DMOWrapperFilter {}
+
+[
+ helpstring("WM ASF Reader"),
+ threading(both),
+ uuid(187463a0-5bb7-11d3-acbe-0080c75e246e),
+]
+coclass WMAsfReader {}
diff --git a/dlls/qasf/qasf_main.c b/dlls/qasf/qasf_main.c
index 5df23649f0..17301b2494 100644
--- a/dlls/qasf/qasf_main.c
+++ b/dlls/qasf/qasf_main.c
@@ -99,6 +99,7 @@ static const IClassFactoryVtbl class_factory_vtbl =
};
static struct class_factory dmo_wrapper_cf = {{&class_factory_vtbl}, dmo_wrapper_create};
+static struct class_factory wmasf_reader_cf = {{&class_factory_vtbl}, wmasf_reader_create};
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved)
{
@@ -116,6 +117,8 @@ HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **out)
if (IsEqualGUID(clsid, &CLSID_DMOWrapperFilter))
return IClassFactory_QueryInterface(&dmo_wrapper_cf.IClassFactory_iface, iid, out);
+ if (IsEqualIID(clsid, &CLSID_WMAsfReader))
+ return IClassFactory_QueryInterface(&wmasf_reader_cf.IClassFactory_iface, iid, out);
FIXME("%s not available, returning CLASS_E_CLASSNOTAVAILABLE.\n", debugstr_guid(clsid));
return CLASS_E_CLASSNOTAVAILABLE;
diff --git a/dlls/qasf/qasf_private.h b/dlls/qasf/qasf_private.h
index bdb2e433b2..6564194c9e 100644
--- a/dlls/qasf/qasf_private.h
+++ b/dlls/qasf/qasf_private.h
@@ -30,5 +30,6 @@
#include "wine/strmbase.h"
HRESULT dmo_wrapper_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN;
+HRESULT wmasf_reader_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN;
#endif /* QASF_PRIVATE_H */
diff --git a/dlls/qasf/tests/Makefile.in b/dlls/qasf/tests/Makefile.in
index 793f0d2c4b..b622ccf599 100644
--- a/dlls/qasf/tests/Makefile.in
+++ b/dlls/qasf/tests/Makefile.in
@@ -2,4 +2,5 @@ TESTDLL = qasf.dll
IMPORTS = strmbase dmoguids strmiids uuid msdmo ole32
C_SRCS = \
- dmowrapper.c
+ dmowrapper.c \
+ wmasf.c
diff --git a/dlls/qasf/tests/wmasf.c b/dlls/qasf/tests/wmasf.c
new file mode 100644
index 0000000000..b82aa3a053
--- /dev/null
+++ b/dlls/qasf/tests/wmasf.c
@@ -0,0 +1,182 @@
+/*
+ * WM ASF reader unit tests
+ *
+ * Copyright 2019 Zebediah Figura
+ * Copyright 2020 Jactry Zeng for CodeWeavers
+ *
+ * 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
+ */
+
+#define COBJMACROS
+
+#include "dshow.h"
+#include "wine/strmbase.h"
+#include "wine/test.h"
+
+static IBaseFilter *create_wmasf_reader(void)
+{
+ IBaseFilter *filter = NULL;
+ HRESULT hr;
+
+ hr = CoCreateInstance(&CLSID_WMAsfReader, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IBaseFilter, (void **)&filter);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ return filter;
+}
+
+#define expected_ref(obj,ref) expect_ref_((IUnknown*)obj, ref, __LINE__)
+static void expect_ref_(IUnknown* obj, ULONG expected_refcount, int line)
+{
+ ULONG refcount;
+ IUnknown_AddRef(obj);
+ refcount = IUnknown_Release(obj);
+ ok_(__FILE__, line)(refcount == expected_refcount, "Unexpected refcount %d, expected %d.\n",
+ refcount, expected_refcount);
+}
+
+#define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
+static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported)
+{
+ IUnknown *iface = iface_ptr;
+ HRESULT hr, expected_hr;
+ IUnknown *unk;
+
+ expected_hr = supported ? S_OK : E_NOINTERFACE;
+
+ hr = IUnknown_QueryInterface(iface, iid, (void **)&unk);
+ ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x, expected %#x.\n", hr, expected_hr);
+ if (SUCCEEDED(hr))
+ IUnknown_Release(unk);
+}
+
+static void test_interfaces(void)
+{
+ IBaseFilter *filter = create_wmasf_reader();
+
+ check_interface(filter, &IID_IBaseFilter, TRUE);
+ check_interface(filter, &IID_IMediaFilter, TRUE);
+ todo_wine check_interface(filter, &IID_IFileSourceFilter, TRUE);
+ check_interface(filter, &IID_IPersist, TRUE);
+ check_interface(filter, &IID_IUnknown, TRUE);
+
+ check_interface(filter, &IID_IAMFilterMiscFlags, FALSE);
+ check_interface(filter, &IID_IMediaSeeking, FALSE);
+
+ IBaseFilter_Release(filter);
+}
+
+static const GUID test_iid = {0x33333333};
+static LONG outer_ref = 1;
+
+static HRESULT WINAPI outer_QueryInterface(IUnknown *iface, REFIID iid, void **out)
+{
+ if (IsEqualGUID(iid, &IID_IUnknown) ||
+ IsEqualGUID(iid, &IID_IBaseFilter) ||
+ IsEqualGUID(iid, &test_iid))
+ {
+ *out = (IUnknown *)0xdeadbeef;
+ return S_OK;
+ }
+ ok(0, "Unexpected call %s.\n", wine_dbgstr_guid(iid));
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI outer_AddRef(IUnknown *iface)
+{
+ return InterlockedIncrement(&outer_ref);
+}
+
+static ULONG WINAPI outer_Release(IUnknown *iface)
+{
+ return InterlockedDecrement(&outer_ref);
+}
+
+static const IUnknownVtbl outer_vtbl =
+{
+ outer_QueryInterface,
+ outer_AddRef,
+ outer_Release,
+};
+
+static IUnknown test_outer = {&outer_vtbl};
+
+static void test_aggregation(void)
+{
+ IBaseFilter *filter, *filter2;
+ IUnknown *unk, *unk2;
+ HRESULT hr;
+ ULONG ref;
+
+ filter = (IBaseFilter *)0xdeadbeef;
+ hr = CoCreateInstance(&CLSID_WMAsfReader, &test_outer, CLSCTX_INPROC_SERVER,
+ &IID_IBaseFilter, (void **)&filter);
+ ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr);
+ ok(!filter, "Got interface %p.\n", filter);
+
+ hr = CoCreateInstance(&CLSID_WMAsfReader, &test_outer, CLSCTX_INPROC_SERVER,
+ &IID_IUnknown, (void **)&unk);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
+ ok(unk != &test_outer, "Returned IUnknown should not be outer IUnknown.\n");
+ expected_ref(unk, 1);
+
+ ref = IUnknown_AddRef(unk);
+ ok(ref == 2, "Got unexpected refcount %d.\n", ref);
+ ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
+
+ ref = IUnknown_Release(unk);
+ ok(ref == 1, "Got unexpected refcount %d.\n", ref);
+ ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
+
+ hr = IUnknown_QueryInterface(unk, &IID_IUnknown, (void **)&unk2);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(unk2 == unk, "Got unexpected IUnknown %p.\n", unk2);
+ IUnknown_Release(unk2);
+
+ hr = IUnknown_QueryInterface(unk, &IID_IBaseFilter, (void **)&filter);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IBaseFilter_QueryInterface(filter, &IID_IUnknown, (void **)&unk2);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(unk2 == (IUnknown *)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2);
+
+ hr = IBaseFilter_QueryInterface(filter, &IID_IBaseFilter, (void **)&filter2);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(filter2 == (IBaseFilter *)0xdeadbeef, "Got unexpected IBaseFilter %p.\n", filter2);
+
+ hr = IUnknown_QueryInterface(unk, &test_iid, (void **)&unk2);
+ ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr);
+ ok(!unk2, "Got unexpected IUnknown %p.\n", unk2);
+
+ hr = IBaseFilter_QueryInterface(filter, &test_iid, (void **)&unk2);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(unk2 == (IUnknown *)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2);
+
+ IBaseFilter_Release(filter);
+ ref = IUnknown_Release(unk);
+ ok(!ref, "Got unexpected refcount %d.\n", ref);
+ ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
+}
+
+START_TEST(wmasf)
+{
+ CoInitializeEx(NULL, COINIT_MULTITHREADED);
+
+ test_interfaces();
+ test_aggregation();
+
+ CoUninitialize();
+}
diff --git a/dlls/qasf/wmasf.c b/dlls/qasf/wmasf.c
new file mode 100644
index 0000000000..04aaf21367
--- /dev/null
+++ b/dlls/qasf/wmasf.c
@@ -0,0 +1,67 @@
+/*
+ * WM ASF reader
+ *
+ * Copyright 2020 Jactry Zeng for CodeWeavers
+ *
+ * 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
+ */
+
+#include "qasf_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(qasf);
+
+struct wmasf_reader
+{
+ struct strmbase_filter filter;
+};
+
+static inline struct wmasf_reader *impl_reader_from_strmbase_filter(struct strmbase_filter *iface)
+{
+ return CONTAINING_RECORD(iface, struct wmasf_reader, filter);
+}
+
+static struct strmbase_pin *wmasf_reader_get_pin(struct strmbase_filter *iface, unsigned int index)
+{
+ return NULL;
+}
+
+static void wmasf_reader_destroy(struct strmbase_filter *iface)
+{
+ struct wmasf_reader *filter = impl_reader_from_strmbase_filter(iface);
+
+ strmbase_filter_cleanup(&filter->filter);
+ free(filter);
+}
+
+static struct strmbase_filter_ops filter_ops =
+{
+ .filter_get_pin = wmasf_reader_get_pin,
+ .filter_destroy = wmasf_reader_destroy,
+};
+
+HRESULT wmasf_reader_create(IUnknown *outer, IUnknown **out)
+{
+ struct wmasf_reader *object;
+
+ if (!(object = calloc(sizeof(*object), 1)))
+ return E_OUTOFMEMORY;
+
+ strmbase_filter_init(&object->filter, outer, &CLSID_WMAsfReader, &filter_ops);
+
+ TRACE("Created WM ASF reader %p.\n", object);
+ *out = &object->filter.IUnknown_inner;
+
+ return S_OK;
+}
--
2.26.0
4
4
06 Apr '20
Signed-off-by: Brendan Shanks <bshanks(a)codeweavers.com>
---
The Vulkan loader just added exports for
vkGetPhysicalDeviceSurfaceCapabilities2KHR and
vkGetPhysicalDeviceSurfaceFormats2KHR
(see https://github.com/KhronosGroup/Vulkan-Loader/issues/342) and it
will take time for this version to filter down to users.
Until it does, emulate the functions using the original non-2 versions.
dlls/winemac.drv/vulkan.c | 32 +++++
dlls/winevulkan/make_vulkan | 7 +-
dlls/winevulkan/vulkan_thunks.c | 46 +++++++
dlls/winevulkan/vulkan_thunks.h | 19 +++
dlls/winex11.drv/vulkan.c | 60 ++++++++
include/wine/vulkan.h | 234 ++++++++++++++++++--------------
include/wine/vulkan_driver.h | 8 +-
7 files changed, 301 insertions(+), 105 deletions(-)
diff --git a/dlls/winemac.drv/vulkan.c b/dlls/winemac.drv/vulkan.c
index 360dd02f7b..5d15eeda2b 100644
--- a/dlls/winemac.drv/vulkan.c
+++ b/dlls/winemac.drv/vulkan.c
@@ -86,7 +86,9 @@ static void (*pvkDestroySwapchainKHR)(VkDevice, VkSwapchainKHR, const VkAllocati
static VkResult (*pvkEnumerateInstanceExtensionProperties)(const char *, uint32_t *, VkExtensionProperties *);
static void * (*pvkGetDeviceProcAddr)(VkDevice, const char *);
static void * (*pvkGetInstanceProcAddr)(VkInstance, const char *);
+static VkResult (*pvkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *, VkSurfaceCapabilities2KHR *);
static VkResult (*pvkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice, VkSurfaceKHR, VkSurfaceCapabilitiesKHR *);
+static VkResult (*pvkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *, uint32_t *, VkSurfaceFormat2KHR *);
static VkResult (*pvkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkSurfaceFormatKHR *);
static VkResult (*pvkGetPhysicalDeviceSurfacePresentModesKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkPresentModeKHR *);
static VkResult (*pvkGetPhysicalDeviceSurfaceSupportKHR)(VkPhysicalDevice, uint32_t, VkSurfaceKHR, VkBool32 *);
@@ -122,7 +124,9 @@ static BOOL WINAPI wine_vk_init(INIT_ONCE *once, void *param, void **context)
LOAD_FUNCPTR(vkEnumerateInstanceExtensionProperties)
LOAD_FUNCPTR(vkGetDeviceProcAddr)
LOAD_FUNCPTR(vkGetInstanceProcAddr)
+ LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceCapabilities2KHR)
LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceCapabilitiesKHR)
+ LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceFormats2KHR)
LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceFormatsKHR)
LOAD_FUNCPTR(vkGetPhysicalDeviceSurfacePresentModesKHR)
LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceSupportKHR)
@@ -441,6 +445,19 @@ static void *macdrv_vkGetInstanceProcAddr(VkInstance instance, const char *name)
return pvkGetInstanceProcAddr(instance, name);
}
+static VkResult macdrv_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice phys_dev,
+ const VkPhysicalDeviceSurfaceInfo2KHR *surface_info, VkSurfaceCapabilities2KHR *capabilities)
+{
+ VkPhysicalDeviceSurfaceInfo2KHR surface_info_host;
+
+ TRACE("%p, %p, %p\n", phys_dev, surface_info, capabilities);
+
+ surface_info_host = *surface_info;
+ surface_info_host.surface = surface_from_handle(surface_info->surface)->surface;
+
+ return pvkGetPhysicalDeviceSurfaceCapabilities2KHR(phys_dev, &surface_info_host, capabilities);
+}
+
static VkResult macdrv_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice phys_dev,
VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR *capabilities)
{
@@ -452,6 +469,19 @@ static VkResult macdrv_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevic
capabilities);
}
+static VkResult macdrv_vkGetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice phys_dev,
+ const VkPhysicalDeviceSurfaceInfo2KHR *surface_info, uint32_t *count, VkSurfaceFormat2KHR *formats)
+{
+ VkPhysicalDeviceSurfaceInfo2KHR surface_info_host;
+
+ TRACE("%p, %p, %p, %p\n", phys_dev, surface_info, count, formats);
+
+ surface_info_host = *surface_info;
+ surface_info_host.surface = surface_from_handle(surface_info->surface)->surface;
+
+ return pvkGetPhysicalDeviceSurfaceFormats2KHR(phys_dev, &surface_info_host, count, formats);
+}
+
static VkResult macdrv_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice phys_dev,
VkSurfaceKHR surface, uint32_t *count, VkSurfaceFormatKHR *formats)
{
@@ -542,7 +572,9 @@ static const struct vulkan_funcs vulkan_funcs =
macdrv_vkGetDeviceProcAddr,
macdrv_vkGetInstanceProcAddr,
NULL,
+ macdrv_vkGetPhysicalDeviceSurfaceCapabilities2KHR,
macdrv_vkGetPhysicalDeviceSurfaceCapabilitiesKHR,
+ macdrv_vkGetPhysicalDeviceSurfaceFormats2KHR,
macdrv_vkGetPhysicalDeviceSurfaceFormatsKHR,
macdrv_vkGetPhysicalDeviceSurfacePresentModesKHR,
macdrv_vkGetPhysicalDeviceSurfaceSupportKHR,
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan
index 3593410041..fa1aa754c7 100755
--- a/dlls/winevulkan/make_vulkan
+++ b/dlls/winevulkan/make_vulkan
@@ -95,7 +95,6 @@ BLACKLISTED_EXTENSIONS = [
"VK_EXT_validation_features",
"VK_EXT_validation_flags",
"VK_KHR_display", # Needs WSI work.
- "VK_KHR_get_surface_capabilities2",
"VK_KHR_surface_protected_capabilities",
# Device extensions
@@ -138,7 +137,7 @@ CORE_EXTENSIONS = [
# Functions part of our winevulkan graphics driver interface.
# DRIVER_VERSION should be bumped on any change to driver interface
# in FUNCTION_OVERRIDES
-DRIVER_VERSION = 7
+DRIVER_VERSION = 8
# Table of functions for which we have a special implementation.
# These are regular device / instance functions for which we need
@@ -185,6 +184,10 @@ FUNCTION_OVERRIDES = {
"vkGetPhysicalDeviceSurfaceFormatsKHR" : {"dispatch" : True, "driver" : True, "thunk" : True},
"vkGetPhysicalDeviceSurfacePresentModesKHR" : {"dispatch" : True, "driver" : True, "thunk" : True},
+ # VK_KHR_get_surface_capabilities2
+ "vkGetPhysicalDeviceSurfaceCapabilities2KHR" : {"dispatch" : True, "driver" : True, "thunk" : True},
+ "vkGetPhysicalDeviceSurfaceFormats2KHR" : {"dispatch" : True, "driver" : True, "thunk" : True},
+
# VK_KHR_win32_surface
"vkCreateWin32SurfaceKHR" : {"dispatch" : True, "driver" : True, "thunk" : True},
"vkGetPhysicalDeviceWin32PresentationSupportKHR" : {"dispatch" : True, "driver" : True, "thunk" : True},
diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c
index fecf9ab502..2e33ab1e32 100644
--- a/dlls/winevulkan/vulkan_thunks.c
+++ b/dlls/winevulkan/vulkan_thunks.c
@@ -1159,6 +1159,15 @@ static inline void convert_VkPhysicalDeviceProperties2_host_to_win(const VkPhysi
convert_VkPhysicalDeviceProperties_host_to_win(&in->properties, &out->properties);
}
+static inline void convert_VkPhysicalDeviceSurfaceInfo2KHR_win_to_host(const VkPhysicalDeviceSurfaceInfo2KHR *in, VkPhysicalDeviceSurfaceInfo2KHR_host *out)
+{
+ if (!in) return;
+
+ out->sType = in->sType;
+ out->pNext = in->pNext;
+ out->surface = in->surface;
+}
+
static inline void convert_VkPipelineExecutableInfoKHR_win_to_host(const VkPipelineExecutableInfoKHR *in, VkPipelineExecutableInfoKHR_host *out)
{
if (!in) return;
@@ -4348,12 +4357,46 @@ static VkResult WINAPI wine_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesC
return physicalDevice->instance->funcs.p_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV(physicalDevice->phys_dev, pCombinationCount, pCombinations);
}
+static VkResult WINAPI wine_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, VkSurfaceCapabilities2KHR *pSurfaceCapabilities)
+{
+#if defined(USE_STRUCT_CONVERSION)
+ VkResult result;
+ VkPhysicalDeviceSurfaceInfo2KHR_host pSurfaceInfo_host;
+ TRACE("%p, %p, %p\n", physicalDevice, pSurfaceInfo, pSurfaceCapabilities);
+
+ convert_VkPhysicalDeviceSurfaceInfo2KHR_win_to_host(pSurfaceInfo, &pSurfaceInfo_host);
+ result = physicalDevice->instance->funcs.p_vkGetPhysicalDeviceSurfaceCapabilities2KHR(physicalDevice->phys_dev, &pSurfaceInfo_host, pSurfaceCapabilities);
+
+ return result;
+#else
+ TRACE("%p, %p, %p\n", physicalDevice, pSurfaceInfo, pSurfaceCapabilities);
+ return physicalDevice->instance->funcs.p_vkGetPhysicalDeviceSurfaceCapabilities2KHR(physicalDevice->phys_dev, pSurfaceInfo, pSurfaceCapabilities);
+#endif
+}
+
VkResult WINAPI wine_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)
{
TRACE("%p, 0x%s, %p\n", physicalDevice, wine_dbgstr_longlong(surface), pSurfaceCapabilities);
return physicalDevice->instance->funcs.p_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice->phys_dev, surface, pSurfaceCapabilities);
}
+static VkResult WINAPI wine_vkGetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, uint32_t *pSurfaceFormatCount, VkSurfaceFormat2KHR *pSurfaceFormats)
+{
+#if defined(USE_STRUCT_CONVERSION)
+ VkResult result;
+ VkPhysicalDeviceSurfaceInfo2KHR_host pSurfaceInfo_host;
+ TRACE("%p, %p, %p, %p\n", physicalDevice, pSurfaceInfo, pSurfaceFormatCount, pSurfaceFormats);
+
+ convert_VkPhysicalDeviceSurfaceInfo2KHR_win_to_host(pSurfaceInfo, &pSurfaceInfo_host);
+ result = physicalDevice->instance->funcs.p_vkGetPhysicalDeviceSurfaceFormats2KHR(physicalDevice->phys_dev, &pSurfaceInfo_host, pSurfaceFormatCount, pSurfaceFormats);
+
+ return result;
+#else
+ TRACE("%p, %p, %p, %p\n", physicalDevice, pSurfaceInfo, pSurfaceFormatCount, pSurfaceFormats);
+ return physicalDevice->instance->funcs.p_vkGetPhysicalDeviceSurfaceFormats2KHR(physicalDevice->phys_dev, pSurfaceInfo, pSurfaceFormatCount, pSurfaceFormats);
+#endif
+}
+
VkResult WINAPI wine_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pSurfaceFormatCount, VkSurfaceFormatKHR *pSurfaceFormats)
{
TRACE("%p, 0x%s, %p, %p\n", physicalDevice, wine_dbgstr_longlong(surface), pSurfaceFormatCount, pSurfaceFormats);
@@ -4986,7 +5029,9 @@ static const struct vulkan_func vk_instance_dispatch_table[] =
{"vkGetPhysicalDeviceSparseImageFormatProperties2", &wine_vkGetPhysicalDeviceSparseImageFormatProperties2},
{"vkGetPhysicalDeviceSparseImageFormatProperties2KHR", &wine_vkGetPhysicalDeviceSparseImageFormatProperties2KHR},
{"vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV", &wine_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV},
+ {"vkGetPhysicalDeviceSurfaceCapabilities2KHR", &wine_vkGetPhysicalDeviceSurfaceCapabilities2KHR},
{"vkGetPhysicalDeviceSurfaceCapabilitiesKHR", &wine_vkGetPhysicalDeviceSurfaceCapabilitiesKHR},
+ {"vkGetPhysicalDeviceSurfaceFormats2KHR", &wine_vkGetPhysicalDeviceSurfaceFormats2KHR},
{"vkGetPhysicalDeviceSurfaceFormatsKHR", &wine_vkGetPhysicalDeviceSurfaceFormatsKHR},
{"vkGetPhysicalDeviceSurfacePresentModesKHR", &wine_vkGetPhysicalDeviceSurfacePresentModesKHR},
{"vkGetPhysicalDeviceSurfaceSupportKHR", &wine_vkGetPhysicalDeviceSurfaceSupportKHR},
@@ -5170,6 +5215,7 @@ static const char * const vk_instance_extensions[] =
"VK_KHR_external_memory_capabilities",
"VK_KHR_external_semaphore_capabilities",
"VK_KHR_get_physical_device_properties2",
+ "VK_KHR_get_surface_capabilities2",
"VK_KHR_surface",
"VK_KHR_win32_surface",
};
diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h
index 01c1efb277..6805113bba 100644
--- a/dlls/winevulkan/vulkan_thunks.h
+++ b/dlls/winevulkan/vulkan_thunks.h
@@ -726,6 +726,13 @@ typedef struct VkPhysicalDeviceProperties2_host
VkPhysicalDeviceProperties_host properties;
} VkPhysicalDeviceProperties2_host;
+typedef struct VkPhysicalDeviceSurfaceInfo2KHR_host
+{
+ VkStructureType sType;
+ const void *pNext;
+ VkSurfaceKHR surface;
+} VkPhysicalDeviceSurfaceInfo2KHR_host;
+
typedef struct VkPipelineExecutableInfoKHR_host
{
VkStructureType sType;
@@ -1359,7 +1366,17 @@ struct vulkan_instance_funcs
void (*p_vkGetPhysicalDeviceSparseImageFormatProperties2)(VkPhysicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2 *, uint32_t *, VkSparseImageFormatProperties2 *);
void (*p_vkGetPhysicalDeviceSparseImageFormatProperties2KHR)(VkPhysicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2 *, uint32_t *, VkSparseImageFormatProperties2 *);
VkResult (*p_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV)(VkPhysicalDevice, uint32_t *, VkFramebufferMixedSamplesCombinationNV *);
+#if defined(USE_STRUCT_CONVERSION)
+ VkResult (*p_vkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR_host *, VkSurfaceCapabilities2KHR *);
+#else
+ VkResult (*p_vkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *, VkSurfaceCapabilities2KHR *);
+#endif
VkResult (*p_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice, VkSurfaceKHR, VkSurfaceCapabilitiesKHR *);
+#if defined(USE_STRUCT_CONVERSION)
+ VkResult (*p_vkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR_host *, uint32_t *, VkSurfaceFormat2KHR *);
+#else
+ VkResult (*p_vkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *, uint32_t *, VkSurfaceFormat2KHR *);
+#endif
VkResult (*p_vkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkSurfaceFormatKHR *);
VkResult (*p_vkGetPhysicalDeviceSurfacePresentModesKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkPresentModeKHR *);
VkResult (*p_vkGetPhysicalDeviceSurfaceSupportKHR)(VkPhysicalDevice, uint32_t, VkSurfaceKHR, VkBool32 *);
@@ -1637,7 +1654,9 @@ struct vulkan_instance_funcs
USE_VK_FUNC(vkGetPhysicalDeviceSparseImageFormatProperties2) \
USE_VK_FUNC(vkGetPhysicalDeviceSparseImageFormatProperties2KHR) \
USE_VK_FUNC(vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV) \
+ USE_VK_FUNC(vkGetPhysicalDeviceSurfaceCapabilities2KHR) \
USE_VK_FUNC(vkGetPhysicalDeviceSurfaceCapabilitiesKHR) \
+ USE_VK_FUNC(vkGetPhysicalDeviceSurfaceFormats2KHR) \
USE_VK_FUNC(vkGetPhysicalDeviceSurfaceFormatsKHR) \
USE_VK_FUNC(vkGetPhysicalDeviceSurfacePresentModesKHR) \
USE_VK_FUNC(vkGetPhysicalDeviceSurfaceSupportKHR) \
diff --git a/dlls/winex11.drv/vulkan.c b/dlls/winex11.drv/vulkan.c
index 28ae1a9e0e..caef8c9928 100644
--- a/dlls/winex11.drv/vulkan.c
+++ b/dlls/winex11.drv/vulkan.c
@@ -85,7 +85,9 @@ static VkResult (*pvkGetDeviceGroupSurfacePresentModesKHR)(VkDevice, VkSurfaceKH
static void * (*pvkGetDeviceProcAddr)(VkDevice, const char *);
static void * (*pvkGetInstanceProcAddr)(VkInstance, const char *);
static VkResult (*pvkGetPhysicalDevicePresentRectanglesKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkRect2D *);
+static VkResult (*pvkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *, VkSurfaceCapabilities2KHR *);
static VkResult (*pvkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice, VkSurfaceKHR, VkSurfaceCapabilitiesKHR *);
+static VkResult (*pvkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *, uint32_t *, VkSurfaceFormat2KHR *);
static VkResult (*pvkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkSurfaceFormatKHR *);
static VkResult (*pvkGetPhysicalDeviceSurfacePresentModesKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkPresentModeKHR *);
static VkResult (*pvkGetPhysicalDeviceSurfaceSupportKHR)(VkPhysicalDevice, uint32_t, VkSurfaceKHR, VkBool32 *);
@@ -122,7 +124,9 @@ static BOOL WINAPI wine_vk_init(INIT_ONCE *once, void *param, void **context)
LOAD_FUNCPTR(vkEnumerateInstanceExtensionProperties)
LOAD_FUNCPTR(vkGetDeviceProcAddr)
LOAD_FUNCPTR(vkGetInstanceProcAddr)
+ LOAD_OPTIONAL_FUNCPTR(vkGetPhysicalDeviceSurfaceCapabilities2KHR)
LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceCapabilitiesKHR)
+ LOAD_OPTIONAL_FUNCPTR(vkGetPhysicalDeviceSurfaceFormats2KHR)
LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceFormatsKHR)
LOAD_FUNCPTR(vkGetPhysicalDeviceSurfacePresentModesKHR)
LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceSupportKHR)
@@ -456,6 +460,25 @@ static VkResult X11DRV_vkGetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice
return pvkGetPhysicalDevicePresentRectanglesKHR(phys_dev, x11_surface->surface, count, rects);
}
+static VkResult X11DRV_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice phys_dev,
+ const VkPhysicalDeviceSurfaceInfo2KHR *surface_info, VkSurfaceCapabilities2KHR *capabilities)
+{
+ VkPhysicalDeviceSurfaceInfo2KHR surface_info_host;
+ TRACE("%p, %p, %p\n", phys_dev, surface_info, capabilities);
+
+ surface_info_host = *surface_info;
+ surface_info_host.surface = surface_from_handle(surface_info->surface)->surface;
+
+ if (pvkGetPhysicalDeviceSurfaceCapabilities2KHR)
+ return pvkGetPhysicalDeviceSurfaceCapabilities2KHR(phys_dev, &surface_info_host, capabilities);
+
+ /* Until the loader version exporting this function is common, emulate it using the older non-2 version. */
+ if (surface_info->pNext || capabilities->pNext)
+ FIXME("Emulating vkGetPhysicalDeviceSurfaceCapabilities2KHR with vkGetPhysicalDeviceSurfaceCapabilitiesKHR, pNext is ignored.\n");
+
+ return pvkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev, surface_info_host.surface, &capabilities->surfaceCapabilities);
+}
+
static VkResult X11DRV_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice phys_dev,
VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR *capabilities)
{
@@ -466,6 +489,41 @@ static VkResult X11DRV_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevic
return pvkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev, x11_surface->surface, capabilities);
}
+static VkResult X11DRV_vkGetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice phys_dev,
+ const VkPhysicalDeviceSurfaceInfo2KHR *surface_info, uint32_t *count, VkSurfaceFormat2KHR *formats)
+{
+ VkPhysicalDeviceSurfaceInfo2KHR surface_info_host = *surface_info;
+ VkSurfaceFormatKHR *formats_host;
+ uint32_t i;
+ VkResult result;
+ TRACE("%p, %p, %p, %p\n", phys_dev, surface_info, count, formats);
+
+ surface_info_host = *surface_info;
+ surface_info_host.surface = surface_from_handle(surface_info->surface)->surface;
+
+ if (pvkGetPhysicalDeviceSurfaceFormats2KHR)
+ return pvkGetPhysicalDeviceSurfaceFormats2KHR(phys_dev, &surface_info_host, count, formats);
+
+ /* Until the loader version exporting this function is common, emulate it using the older non-2 version. */
+ if (surface_info->pNext)
+ FIXME("Emulating vkGetPhysicalDeviceSurfaceFormats2KHR with vkGetPhysicalDeviceSurfaceFormatsKHR, pNext is ignored.\n");
+
+ if (!formats)
+ return pvkGetPhysicalDeviceSurfaceFormatsKHR(phys_dev, surface_info_host.surface, count, NULL);
+
+ formats_host = heap_calloc(*count, sizeof(*formats_host));
+ if (!formats_host) return VK_ERROR_OUT_OF_HOST_MEMORY;
+ result = pvkGetPhysicalDeviceSurfaceFormatsKHR(phys_dev, surface_info_host.surface, count, formats_host);
+ if (result == VK_SUCCESS || result == VK_INCOMPLETE)
+ {
+ for (i = 0; i < *count; i++)
+ formats[i].surfaceFormat = formats_host[i];
+ }
+
+ heap_free(formats_host);
+ return result;
+}
+
static VkResult X11DRV_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice phys_dev,
VkSurfaceKHR surface, uint32_t *count, VkSurfaceFormatKHR *formats)
{
@@ -557,7 +615,9 @@ static const struct vulkan_funcs vulkan_funcs =
X11DRV_vkGetDeviceProcAddr,
X11DRV_vkGetInstanceProcAddr,
X11DRV_vkGetPhysicalDevicePresentRectanglesKHR,
+ X11DRV_vkGetPhysicalDeviceSurfaceCapabilities2KHR,
X11DRV_vkGetPhysicalDeviceSurfaceCapabilitiesKHR,
+ X11DRV_vkGetPhysicalDeviceSurfaceFormats2KHR,
X11DRV_vkGetPhysicalDeviceSurfaceFormatsKHR,
X11DRV_vkGetPhysicalDeviceSurfacePresentModesKHR,
X11DRV_vkGetPhysicalDeviceSurfaceSupportKHR,
diff --git a/include/wine/vulkan.h b/include/wine/vulkan.h
index fe804fd23e..c6d72c49fa 100644
--- a/include/wine/vulkan.h
+++ b/include/wine/vulkan.h
@@ -198,6 +198,8 @@
#define VK_KHR_PERFORMANCE_QUERY_EXTENSION_NAME "VK_KHR_performance_query"
#define VK_KHR_MAINTENANCE2_SPEC_VERSION 1
#define VK_KHR_MAINTENANCE2_EXTENSION_NAME "VK_KHR_maintenance2"
+#define VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION 1
+#define VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME "VK_KHR_get_surface_capabilities2"
#define VK_KHR_VARIABLE_POINTERS_SPEC_VERSION 1
#define VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME "VK_KHR_variable_pointers"
#define VK_EXT_QUEUE_FAMILY_FOREIGN_SPEC_VERSION 1
@@ -2348,6 +2350,9 @@ typedef enum VkStructureType
VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO = 1000117001,
VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO = 1000117002,
VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO = 1000117003,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR = 1000119000,
+ VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR = 1000119001,
+ VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR = 1000119002,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES = 1000120000,
VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS = 1000127000,
VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO = 1000127001,
@@ -4083,20 +4088,6 @@ typedef struct VkSubresourceLayout
VkDeviceSize WINE_VK_ALIGN(8) depthPitch;
} VkSubresourceLayout;
-typedef struct VkSurfaceCapabilitiesKHR
-{
- uint32_t minImageCount;
- uint32_t maxImageCount;
- VkExtent2D currentExtent;
- VkExtent2D minImageExtent;
- VkExtent2D maxImageExtent;
- uint32_t maxImageArrayLayers;
- VkSurfaceTransformFlagsKHR supportedTransforms;
- VkSurfaceTransformFlagBitsKHR currentTransform;
- VkCompositeAlphaFlagsKHR supportedCompositeAlpha;
- VkImageUsageFlags supportedUsageFlags;
-} VkSurfaceCapabilitiesKHR;
-
typedef struct VkSurfaceFormatKHR
{
VkFormat format;
@@ -4673,6 +4664,13 @@ typedef struct VkPhysicalDeviceSparseProperties
VkBool32 residencyNonResidentStrict;
} VkPhysicalDeviceSparseProperties;
+typedef struct VkPhysicalDeviceSurfaceInfo2KHR
+{
+ VkStructureType sType;
+ const void *pNext;
+ VkSurfaceKHR WINE_VK_ALIGN(8) surface;
+} VkPhysicalDeviceSurfaceInfo2KHR;
+
typedef struct VkPhysicalDeviceTimelineSemaphoreFeaturesKHR
{
VkStructureType sType;
@@ -4965,6 +4963,20 @@ typedef struct VkSubpassSampleLocationsEXT
VkSampleLocationsInfoEXT sampleLocationsInfo;
} VkSubpassSampleLocationsEXT;
+typedef struct VkSurfaceCapabilitiesKHR
+{
+ uint32_t minImageCount;
+ uint32_t maxImageCount;
+ VkExtent2D currentExtent;
+ VkExtent2D minImageExtent;
+ VkExtent2D maxImageExtent;
+ uint32_t maxImageArrayLayers;
+ VkSurfaceTransformFlagsKHR supportedTransforms;
+ VkSurfaceTransformFlagBitsKHR currentTransform;
+ VkCompositeAlphaFlagsKHR supportedCompositeAlpha;
+ VkImageUsageFlags supportedUsageFlags;
+} VkSurfaceCapabilitiesKHR;
+
typedef struct VkSwapchainCreateInfoKHR
{
VkStructureType sType;
@@ -5537,20 +5549,26 @@ typedef struct VkSubpassDescriptionDepthStencilResolveKHR
const VkAttachmentReference2KHR *pDepthStencilResolveAttachment;
} VkSubpassDescriptionDepthStencilResolveKHR;
-typedef struct VkVertexInputBindingDivisorDescriptionEXT
+typedef struct VkSurfaceCapabilities2KHR
{
- uint32_t binding;
- uint32_t divisor;
-} VkVertexInputBindingDivisorDescriptionEXT;
+ VkStructureType sType;
+ void *pNext;
+ VkSurfaceCapabilitiesKHR surfaceCapabilities;
+} VkSurfaceCapabilities2KHR;
-typedef struct VkWin32SurfaceCreateInfoKHR
+typedef struct VkViewportWScalingNV
+{
+ float xcoeff;
+ float ycoeff;
+} VkViewportWScalingNV;
+
+typedef struct VkWriteDescriptorSetInlineUniformBlockEXT
{
VkStructureType sType;
const void *pNext;
- VkWin32SurfaceCreateFlagsKHR flags;
- HINSTANCE hinstance;
- HWND hwnd;
-} VkWin32SurfaceCreateInfoKHR;
+ uint32_t dataSize;
+ const void *pData;
+} VkWriteDescriptorSetInlineUniformBlockEXT;
typedef struct VkBindImageMemoryDeviceGroupInfo
{
@@ -5781,13 +5799,13 @@ typedef struct VkPipelineRepresentativeFragmentTestStateCreateInfoNV
VkBool32 representativeFragmentTestEnable;
} VkPipelineRepresentativeFragmentTestStateCreateInfoNV;
-typedef struct VkPipelineVertexInputDivisorStateCreateInfoEXT
+typedef struct VkPipelineViewportExclusiveScissorStateCreateInfoNV
{
VkStructureType sType;
const void *pNext;
- uint32_t vertexBindingDivisorCount;
- const VkVertexInputBindingDivisorDescriptionEXT *pVertexBindingDivisors;
-} VkPipelineVertexInputDivisorStateCreateInfoEXT;
+ uint32_t exclusiveScissorCount;
+ const VkRect2D *pExclusiveScissors;
+} VkPipelineViewportExclusiveScissorStateCreateInfoNV;
typedef struct VkPresentRegionsKHR
{
@@ -5852,13 +5870,14 @@ typedef struct VkSpecializationInfo
const void *pData;
} VkSpecializationInfo;
-typedef struct VkWriteDescriptorSetInlineUniformBlockEXT
+typedef struct VkWin32SurfaceCreateInfoKHR
{
VkStructureType sType;
const void *pNext;
- uint32_t dataSize;
- const void *pData;
-} VkWriteDescriptorSetInlineUniformBlockEXT;
+ VkWin32SurfaceCreateFlagsKHR flags;
+ HINSTANCE hinstance;
+ HWND hwnd;
+} VkWin32SurfaceCreateInfoKHR;
typedef struct VkAttachmentSampleLocationsEXT
{
@@ -6005,12 +6024,29 @@ typedef struct VkPipelineShaderStageCreateInfo
const VkSpecializationInfo *pSpecializationInfo;
} VkPipelineShaderStageCreateInfo;
-typedef struct VkQueueFamilyCheckpointPropertiesNV
+typedef struct VkPipelineViewportWScalingStateCreateInfoNV
{
VkStructureType sType;
- void *pNext;
- VkPipelineStageFlags checkpointExecutionStageMask;
-} VkQueueFamilyCheckpointPropertiesNV;
+ const void *pNext;
+ VkBool32 viewportWScalingEnable;
+ uint32_t viewportCount;
+ const VkViewportWScalingNV *pViewportWScalings;
+} VkPipelineViewportWScalingStateCreateInfoNV;
+
+typedef struct VkRayTracingPipelineCreateInfoNV
+{
+ VkStructureType sType;
+ const void *pNext;
+ VkPipelineCreateFlags flags;
+ uint32_t stageCount;
+ const VkPipelineShaderStageCreateInfo *pStages;
+ uint32_t groupCount;
+ const VkRayTracingShaderGroupCreateInfoNV *pGroups;
+ uint32_t maxRecursionDepth;
+ VkPipelineLayout WINE_VK_ALIGN(8) layout;
+ VkPipeline WINE_VK_ALIGN(8) basePipelineHandle;
+ int32_t basePipelineIndex;
+} VkRayTracingPipelineCreateInfoNV;
typedef struct VkRenderPassSampleLocationsBeginInfoEXT
{
@@ -6043,11 +6079,11 @@ typedef struct VkSubpassDescription
const uint32_t *pPreserveAttachments;
} VkSubpassDescription;
-typedef struct VkViewportWScalingNV
+typedef struct VkVertexInputBindingDivisorDescriptionEXT
{
- float xcoeff;
- float ycoeff;
-} VkViewportWScalingNV;
+ uint32_t binding;
+ uint32_t divisor;
+} VkVertexInputBindingDivisorDescriptionEXT;
typedef struct VkAccelerationStructureInfoNV
{
@@ -6108,28 +6144,33 @@ typedef struct VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT
VkBool32 vertexAttributeInstanceRateZeroDivisor;
} VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT;
-typedef struct VkPipelineViewportExclusiveScissorStateCreateInfoNV
+typedef struct VkPipelineVertexInputDivisorStateCreateInfoEXT
{
VkStructureType sType;
const void *pNext;
- uint32_t exclusiveScissorCount;
- const VkRect2D *pExclusiveScissors;
-} VkPipelineViewportExclusiveScissorStateCreateInfoNV;
+ uint32_t vertexBindingDivisorCount;
+ const VkVertexInputBindingDivisorDescriptionEXT *pVertexBindingDivisors;
+} VkPipelineVertexInputDivisorStateCreateInfoEXT;
-typedef struct VkRayTracingPipelineCreateInfoNV
+typedef struct VkRenderPassCreateInfo
{
VkStructureType sType;
const void *pNext;
- VkPipelineCreateFlags flags;
- uint32_t stageCount;
- const VkPipelineShaderStageCreateInfo *pStages;
- uint32_t groupCount;
- const VkRayTracingShaderGroupCreateInfoNV *pGroups;
- uint32_t maxRecursionDepth;
- VkPipelineLayout WINE_VK_ALIGN(8) layout;
- VkPipeline WINE_VK_ALIGN(8) basePipelineHandle;
- int32_t basePipelineIndex;
-} VkRayTracingPipelineCreateInfoNV;
+ VkRenderPassCreateFlags flags;
+ uint32_t attachmentCount;
+ const VkAttachmentDescription *pAttachments;
+ uint32_t subpassCount;
+ const VkSubpassDescription *pSubpasses;
+ uint32_t dependencyCount;
+ const VkSubpassDependency *pDependencies;
+} VkRenderPassCreateInfo;
+
+typedef struct VkSparseImageMemoryBindInfo
+{
+ VkImage WINE_VK_ALIGN(8) image;
+ uint32_t bindCount;
+ const VkSparseImageMemoryBind *pBinds;
+} VkSparseImageMemoryBindInfo;
typedef struct VkAccelerationStructureCreateInfoNV
{
@@ -6186,34 +6227,21 @@ typedef struct VkPipelineLayoutCreateInfo
const VkPushConstantRange *pPushConstantRanges;
} VkPipelineLayoutCreateInfo;
-typedef struct VkRenderPassCreateInfo
-{
- VkStructureType sType;
- const void *pNext;
- VkRenderPassCreateFlags flags;
- uint32_t attachmentCount;
- const VkAttachmentDescription *pAttachments;
- uint32_t subpassCount;
- const VkSubpassDescription *pSubpasses;
- uint32_t dependencyCount;
- const VkSubpassDependency *pDependencies;
-} VkRenderPassCreateInfo;
-
-typedef struct VkDeviceQueueGlobalPriorityCreateInfoEXT
-{
- VkStructureType sType;
- const void *pNext;
- VkQueueGlobalPriorityEXT globalPriority;
-} VkDeviceQueueGlobalPriorityCreateInfoEXT;
-
-typedef struct VkPipelineViewportWScalingStateCreateInfoNV
+typedef struct VkBindSparseInfo
{
VkStructureType sType;
const void *pNext;
- VkBool32 viewportWScalingEnable;
- uint32_t viewportCount;
- const VkViewportWScalingNV *pViewportWScalings;
-} VkPipelineViewportWScalingStateCreateInfoNV;
+ uint32_t waitSemaphoreCount;
+ const VkSemaphore *pWaitSemaphores;
+ uint32_t bufferBindCount;
+ const VkSparseBufferMemoryBindInfo *pBufferBinds;
+ uint32_t imageOpaqueBindCount;
+ const VkSparseImageOpaqueMemoryBindInfo *pImageOpaqueBinds;
+ uint32_t imageBindCount;
+ const VkSparseImageMemoryBindInfo *pImageBinds;
+ uint32_t signalSemaphoreCount;
+ const VkSemaphore *pSignalSemaphores;
+} VkBindSparseInfo;
typedef struct VkGraphicsPipelineCreateInfo
{
@@ -6238,29 +6266,6 @@ typedef struct VkGraphicsPipelineCreateInfo
int32_t basePipelineIndex;
} VkGraphicsPipelineCreateInfo;
-typedef struct VkSparseImageMemoryBindInfo
-{
- VkImage WINE_VK_ALIGN(8) image;
- uint32_t bindCount;
- const VkSparseImageMemoryBind *pBinds;
-} VkSparseImageMemoryBindInfo;
-
-typedef struct VkBindSparseInfo
-{
- VkStructureType sType;
- const void *pNext;
- uint32_t waitSemaphoreCount;
- const VkSemaphore *pWaitSemaphores;
- uint32_t bufferBindCount;
- const VkSparseBufferMemoryBindInfo *pBufferBinds;
- uint32_t imageOpaqueBindCount;
- const VkSparseImageOpaqueMemoryBindInfo *pImageOpaqueBinds;
- uint32_t imageBindCount;
- const VkSparseImageMemoryBindInfo *pImageBinds;
- uint32_t signalSemaphoreCount;
- const VkSemaphore *pSignalSemaphores;
-} VkBindSparseInfo;
-
typedef struct VkPhysicalDeviceShaderCorePropertiesAMD
{
VkStructureType sType;
@@ -6281,6 +6286,27 @@ typedef struct VkPhysicalDeviceShaderCorePropertiesAMD
uint32_t vgprAllocationGranularity;
} VkPhysicalDeviceShaderCorePropertiesAMD;
+typedef struct VkSurfaceFormat2KHR
+{
+ VkStructureType sType;
+ void *pNext;
+ VkSurfaceFormatKHR surfaceFormat;
+} VkSurfaceFormat2KHR;
+
+typedef struct VkDeviceQueueGlobalPriorityCreateInfoEXT
+{
+ VkStructureType sType;
+ const void *pNext;
+ VkQueueGlobalPriorityEXT globalPriority;
+} VkDeviceQueueGlobalPriorityCreateInfoEXT;
+
+typedef struct VkQueueFamilyCheckpointPropertiesNV
+{
+ VkStructureType sType;
+ void *pNext;
+ VkPipelineStageFlags checkpointExecutionStageMask;
+} VkQueueFamilyCheckpointPropertiesNV;
+
typedef VkResult (VKAPI_PTR *PFN_vkAcquireNextImage2KHR)(VkDevice, const VkAcquireNextImageInfoKHR *, uint32_t *);
typedef VkResult (VKAPI_PTR *PFN_vkAcquireNextImageKHR)(VkDevice, VkSwapchainKHR, uint64_t, VkSemaphore, VkFence, uint32_t *);
typedef VkResult (VKAPI_PTR *PFN_vkAcquirePerformanceConfigurationINTEL)(VkDevice, const VkPerformanceConfigurationAcquireInfoINTEL *, VkPerformanceConfigurationINTEL *);
@@ -6520,7 +6546,9 @@ typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties)(VkP
typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2)(VkPhysicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2 *, uint32_t *, VkSparseImageFormatProperties2 *);
typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR)(VkPhysicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2 *, uint32_t *, VkSparseImageFormatProperties2 *);
typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV)(VkPhysicalDevice, uint32_t *, VkFramebufferMixedSamplesCombinationNV *);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *, VkSurfaceCapabilities2KHR *);
typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice, VkSurfaceKHR, VkSurfaceCapabilitiesKHR *);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *, uint32_t *, VkSurfaceFormat2KHR *);
typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkSurfaceFormatKHR *);
typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkPresentModeKHR *);
typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceSupportKHR)(VkPhysicalDevice, uint32_t, VkSurfaceKHR, VkBool32 *);
@@ -6808,7 +6836,9 @@ void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice
void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo, uint32_t *pPropertyCount, VkSparseImageFormatProperties2 *pProperties);
void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo, uint32_t *pPropertyCount, VkSparseImageFormatProperties2 *pProperties);
VkResult VKAPI_CALL vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV(VkPhysicalDevice physicalDevice, uint32_t *pCombinationCount, VkFramebufferMixedSamplesCombinationNV *pCombinations);
+VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, VkSurfaceCapabilities2KHR *pSurfaceCapabilities);
VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR *pSurfaceCapabilities);
+VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, uint32_t *pSurfaceFormatCount, VkSurfaceFormat2KHR *pSurfaceFormats);
VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pSurfaceFormatCount, VkSurfaceFormatKHR *pSurfaceFormats);
VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pPresentModeCount, VkPresentModeKHR *pPresentModes);
VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32 *pSupported);
diff --git a/include/wine/vulkan_driver.h b/include/wine/vulkan_driver.h
index 02f504e9ae..187cde70ad 100644
--- a/include/wine/vulkan_driver.h
+++ b/include/wine/vulkan_driver.h
@@ -39,7 +39,7 @@
#define __WINE_VULKAN_DRIVER_H
/* Wine internal vulkan driver version, needs to be bumped upon vulkan_funcs changes. */
-#define WINE_VULKAN_DRIVER_VERSION 7
+#define WINE_VULKAN_DRIVER_VERSION 8
struct vulkan_funcs
{
@@ -58,7 +58,9 @@ struct vulkan_funcs
void * (*p_vkGetDeviceProcAddr)(VkDevice, const char *);
void * (*p_vkGetInstanceProcAddr)(VkInstance, const char *);
VkResult (*p_vkGetPhysicalDevicePresentRectanglesKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkRect2D *);
+ VkResult (*p_vkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *, VkSurfaceCapabilities2KHR *);
VkResult (*p_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice, VkSurfaceKHR, VkSurfaceCapabilitiesKHR *);
+ VkResult (*p_vkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *, uint32_t *, VkSurfaceFormat2KHR *);
VkResult (*p_vkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkSurfaceFormatKHR *);
VkResult (*p_vkGetPhysicalDeviceSurfacePresentModesKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkPresentModeKHR *);
VkResult (*p_vkGetPhysicalDeviceSurfaceSupportKHR)(VkPhysicalDevice, uint32_t, VkSurfaceKHR, VkBool32 *);
@@ -116,8 +118,12 @@ static inline void *get_vulkan_driver_instance_proc_addr(
return vulkan_funcs->p_vkGetInstanceProcAddr;
if (!strcmp(name, "GetPhysicalDevicePresentRectanglesKHR"))
return vulkan_funcs->p_vkGetPhysicalDevicePresentRectanglesKHR;
+ if (!strcmp(name, "GetPhysicalDeviceSurfaceCapabilities2KHR"))
+ return vulkan_funcs->p_vkGetPhysicalDeviceSurfaceCapabilities2KHR;
if (!strcmp(name, "GetPhysicalDeviceSurfaceCapabilitiesKHR"))
return vulkan_funcs->p_vkGetPhysicalDeviceSurfaceCapabilitiesKHR;
+ if (!strcmp(name, "GetPhysicalDeviceSurfaceFormats2KHR"))
+ return vulkan_funcs->p_vkGetPhysicalDeviceSurfaceFormats2KHR;
if (!strcmp(name, "GetPhysicalDeviceSurfaceFormatsKHR"))
return vulkan_funcs->p_vkGetPhysicalDeviceSurfaceFormatsKHR;
if (!strcmp(name, "GetPhysicalDeviceSurfacePresentModesKHR"))
--
2.24.1
3
4
Store cubic bezier control points, instead of storing them as
quadratics.
Signed-off-by: Connor McAdams <conmanx360(a)gmail.com>
---
dlls/d2d1/geometry.c | 474 +++++++++++++++++++++++++++++++++++++------
1 file changed, 407 insertions(+), 67 deletions(-)
diff --git a/dlls/d2d1/geometry.c b/dlls/d2d1/geometry.c
index c18b648aef..cd21ef21c5 100644
--- a/dlls/d2d1/geometry.c
+++ b/dlls/d2d1/geometry.c
@@ -48,8 +48,10 @@ enum d2d_vertex_type
{
D2D_VERTEX_TYPE_NONE,
D2D_VERTEX_TYPE_LINE,
- D2D_VERTEX_TYPE_BEZIER,
- D2D_VERTEX_TYPE_SPLIT_BEZIER,
+ D2D_VERTEX_TYPE_QUADRATIC_BEZIER,
+ D2D_VERTEX_TYPE_CUBIC_BEZIER,
+ D2D_VERTEX_TYPE_SPLIT_QUAD_BEZIER,
+ D2D_VERTEX_TYPE_SPLIT_CUBIC_BEZIER,
};
struct d2d_segment_idx
@@ -409,6 +411,68 @@ static void d2d_point_normalise(D2D1_POINT_2F *p)
d2d_point_scale(p, 1.0f / l);
}
+static void d2d_bezier_cubic_to_quad(const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1,
+ const D2D1_POINT_2F *p2, const D2D1_POINT_2F *p3, D2D1_POINT_2F *c0)
+{
+ c0->x = (p1->x + p2->x) * 0.75f;
+ c0->y = (p1->y + p2->y) * 0.75f;
+ c0->x -= (p0->x + p3->x) * 0.25f;
+ c0->y -= (p0->y + p3->y) * 0.25f;
+}
+
+static void d2d_bezier_split_cubic(const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1,
+ const D2D1_POINT_2F *p2, const D2D1_POINT_2F *p3, float t, D2D1_BEZIER_SEGMENT *left,
+ D2D1_BEZIER_SEGMENT *right, D2D1_POINT_2F *center)
+{
+ D2D1_POINT_2F q[4], r[3], mid;
+
+ d2d_point_lerp(&q[0], p0, p1, t);
+ d2d_point_lerp(&q[1], p1, p2, t);
+ d2d_point_lerp(&q[2], p2, p3, t);
+
+ d2d_point_lerp(&r[0], &q[0], &q[1], t);
+ d2d_point_lerp(&r[1], &q[1], &q[2], t);
+ d2d_point_lerp(&mid, &r[0], &r[1], t);
+
+ if (center)
+ *center = mid;
+
+ if (left)
+ {
+ left->point1 = q[0];
+ left->point2 = r[0];
+ left->point3 = mid;
+ }
+
+ if (right)
+ {
+ right->point1 = r[1];
+ right->point2 = q[2];
+ right->point3 = *p3;
+ }
+}
+
+static BOOL d2d_vertex_type_is_bezier(enum d2d_vertex_type t)
+{
+ return (t == D2D_VERTEX_TYPE_QUADRATIC_BEZIER || t == D2D_VERTEX_TYPE_CUBIC_BEZIER ||
+ t == D2D_VERTEX_TYPE_SPLIT_QUAD_BEZIER || t == D2D_VERTEX_TYPE_SPLIT_CUBIC_BEZIER);
+}
+
+static BOOL d2d_vertex_type_is_cubic_bezier(enum d2d_vertex_type t)
+{
+ return (t == D2D_VERTEX_TYPE_CUBIC_BEZIER || t == D2D_VERTEX_TYPE_SPLIT_CUBIC_BEZIER);
+}
+
+static BOOL d2d_vertex_type_is_split_bezier(enum d2d_vertex_type t)
+{
+ return (t == D2D_VERTEX_TYPE_SPLIT_QUAD_BEZIER || t == D2D_VERTEX_TYPE_SPLIT_CUBIC_BEZIER);
+}
+
+static BOOL d2d_vertex_type_is_unsplit_bezier(enum d2d_vertex_type t)
+{
+ return (t == D2D_VERTEX_TYPE_QUADRATIC_BEZIER || t == D2D_VERTEX_TYPE_CUBIC_BEZIER);
+}
+
/* This implementation is based on the paper "Adaptive Precision
* Floating-Point Arithmetic and Fast Robust Geometric Predicates" and
* associated (Public Domain) code by Jonathan Richard Shewchuk. */
@@ -613,37 +677,71 @@ static BOOL d2d_figure_add_vertex(struct d2d_figure *figure, D2D1_POINT_2F verte
return TRUE;
}
-static BOOL d2d_figure_insert_bezier_control(struct d2d_figure *figure, size_t idx, const D2D1_POINT_2F *p)
+static BOOL d2d_figure_insert_bezier_controls(struct d2d_figure *figure, size_t idx, size_t count,
+ const D2D1_POINT_2F **p)
{
+ unsigned int i;
+
if (!d2d_array_reserve((void **)&figure->bezier_controls, &figure->bezier_controls_size,
- figure->bezier_control_count + 1, sizeof(*figure->bezier_controls)))
+ figure->bezier_control_count + count, sizeof(*figure->bezier_controls)))
{
ERR("Failed to grow bezier controls array.\n");
return FALSE;
}
- memmove(&figure->bezier_controls[idx + 1], &figure->bezier_controls[idx],
+ memmove(&figure->bezier_controls[idx + count], &figure->bezier_controls[idx],
(figure->bezier_control_count - idx) * sizeof(*figure->bezier_controls));
- figure->bezier_controls[idx] = *p;
- ++figure->bezier_control_count;
+
+ for (i = 0; i < count; ++i)
+ figure->bezier_controls[idx + i] = *p[i];
+
+ figure->bezier_control_count += count;
return TRUE;
}
-static BOOL d2d_figure_add_bezier_control(struct d2d_figure *figure, const D2D1_POINT_2F *p)
+static BOOL d2d_figure_add_bezier_controls(struct d2d_figure *figure, size_t count, const D2D1_POINT_2F **p)
{
+ unsigned int i;
+
if (!d2d_array_reserve((void **)&figure->bezier_controls, &figure->bezier_controls_size,
- figure->bezier_control_count + 1, sizeof(*figure->bezier_controls)))
+ figure->bezier_control_count + count, sizeof(*figure->bezier_controls)))
{
ERR("Failed to grow bezier controls array.\n");
return FALSE;
}
- figure->bezier_controls[figure->bezier_control_count++] = *p;
+ for (i = 0; i < count; ++i)
+ figure->bezier_controls[figure->bezier_control_count + i] = *p[i];
+
+ figure->bezier_control_count += count;
return TRUE;
}
+static BOOL d2d_figure_insert_bezier_control(struct d2d_figure *figure, size_t idx, const D2D1_POINT_2F *p)
+{
+ return d2d_figure_insert_bezier_controls(figure, idx, 1, &p);
+}
+
+static BOOL d2d_figure_add_bezier_control(struct d2d_figure *figure, const D2D1_POINT_2F *p)
+{
+ return d2d_figure_add_bezier_controls(figure, 1, &p);
+}
+
+static unsigned int d2d_figure_get_bezier_control_count(struct d2d_figure *figure)
+{
+ unsigned int i, control_count;
+
+ for (i = control_count = 0; i < figure->vertex_count; ++i)
+ {
+ if (d2d_vertex_type_is_bezier(figure->vertex_types[i]))
+ ++control_count;
+ }
+
+ return control_count;
+}
+
static void d2d_cdt_edge_rot(struct d2d_cdt_edge_ref *dst, const struct d2d_cdt_edge_ref *src)
{
dst->idx = src->idx;
@@ -1723,15 +1821,28 @@ static BOOL d2d_geometry_intersect_bezier_line(struct d2d_geometry *geometry,
const D2D1_POINT_2F *p[3], *q[2];
const struct d2d_figure *figure;
float y[3], root, theta, d, e;
+ enum d2d_vertex_type type;
+ D2D1_POINT_2F tmp;
size_t next;
figure = &geometry->u.path.figures[idx_p->figure_idx];
+ type = figure->vertex_types[idx_p->vertex_idx];
p[0] = &figure->vertices[idx_p->vertex_idx];
- p[1] = &figure->bezier_controls[idx_p->control_idx];
next = idx_p->vertex_idx + 1;
if (next == figure->vertex_count)
next = 0;
p[2] = &figure->vertices[next];
+ if (d2d_vertex_type_is_cubic_bezier(type))
+ {
+ d2d_bezier_cubic_to_quad(p[0],
+ &figure->bezier_controls[idx_p->control_idx],
+ &figure->bezier_controls[idx_p->control_idx + 1],
+ p[2], &tmp);
+
+ p[1] = &tmp;
+ }
+ else
+ p[1] = &figure->bezier_controls[idx_p->control_idx];
figure = &geometry->u.path.figures[idx_q->figure_idx];
q[0] = &figure->vertices[idx_q->vertex_idx];
@@ -1799,25 +1910,48 @@ static BOOL d2d_geometry_intersect_bezier_bezier(struct d2d_geometry *geometry,
const D2D1_POINT_2F *p[3], *q[3];
const struct d2d_figure *figure;
D2D_RECT_F p_bounds, q_bounds;
- D2D1_POINT_2F intersection;
+ D2D1_POINT_2F intersection, tmp_p, tmp_q;
+ enum d2d_vertex_type type_p, type_q;
float centre_p, centre_q;
size_t next;
figure = &geometry->u.path.figures[idx_p->figure_idx];
+ type_p = figure->vertex_types[idx_p->vertex_idx];
p[0] = &figure->vertices[idx_p->vertex_idx];
- p[1] = &figure->bezier_controls[idx_p->control_idx];
next = idx_p->vertex_idx + 1;
if (next == figure->vertex_count)
next = 0;
p[2] = &figure->vertices[next];
+ if (d2d_vertex_type_is_cubic_bezier(type_p))
+ {
+ d2d_bezier_cubic_to_quad(p[0],
+ &figure->bezier_controls[idx_p->control_idx],
+ &figure->bezier_controls[idx_p->control_idx + 1],
+ p[2], &tmp_p);
+
+ p[1] = &tmp_p;
+ }
+ else
+ p[1] = &figure->bezier_controls[idx_p->control_idx];
figure = &geometry->u.path.figures[idx_q->figure_idx];
+ type_q = figure->vertex_types[idx_q->vertex_idx];
q[0] = &figure->vertices[idx_q->vertex_idx];
- q[1] = &figure->bezier_controls[idx_q->control_idx];
next = idx_q->vertex_idx + 1;
if (next == figure->vertex_count)
next = 0;
q[2] = &figure->vertices[next];
+ if (d2d_vertex_type_is_cubic_bezier(type_q))
+ {
+ d2d_bezier_cubic_to_quad(q[0],
+ &figure->bezier_controls[idx_q->control_idx],
+ &figure->bezier_controls[idx_q->control_idx + 1],
+ q[2], &tmp_q);
+
+ q[1] = &tmp_q;
+ }
+ else
+ q[1] = &figure->bezier_controls[idx_q->control_idx];
d2d_rect_get_bezier_segment_bounds(&p_bounds, p[0], p[1], p[2], start_p, end_p);
d2d_rect_get_bezier_segment_bounds(&q_bounds, q[0], q[1], q[2], start_q, end_q);
@@ -1861,9 +1995,10 @@ static BOOL d2d_geometry_apply_intersections(struct d2d_geometry *geometry,
{
size_t vertex_offset, control_offset, next, i;
struct d2d_geometry_intersection *inter;
- enum d2d_vertex_type vertex_type;
- const D2D1_POINT_2F *p[3];
+ enum d2d_vertex_type vertex_type, split_type;
+ const D2D1_POINT_2F *p[4], *c[2];
struct d2d_figure *figure;
+ D2D1_BEZIER_SEGMENT b[2];
D2D1_POINT_2F q[2];
float t, t_prev;
@@ -1875,7 +2010,7 @@ static BOOL d2d_geometry_apply_intersections(struct d2d_geometry *geometry,
figure = &geometry->u.path.figures[inter->figure_idx];
vertex_type = figure->vertex_types[inter->vertex_idx + vertex_offset];
- if (vertex_type != D2D_VERTEX_TYPE_BEZIER && vertex_type != D2D_VERTEX_TYPE_SPLIT_BEZIER)
+ if (!d2d_vertex_type_is_bezier(vertex_type))
{
if (!d2d_figure_insert_vertex(&geometry->u.path.figures[inter->figure_idx],
inter->vertex_idx + vertex_offset + 1, inter->p))
@@ -1902,19 +2037,43 @@ static BOOL d2d_geometry_apply_intersections(struct d2d_geometry *geometry,
next = inter->vertex_idx + vertex_offset + 1;
if (next == figure->vertex_count)
next = 0;
- p[2] = &figure->vertices[next];
- d2d_point_lerp(&q[0], p[0], p[1], t);
- d2d_point_lerp(&q[1], p[1], p[2], t);
+ if (d2d_vertex_type_is_cubic_bezier(vertex_type))
+ {
+ p[2] = &figure->bezier_controls[inter->control_idx + control_offset + 1];
+ p[3] = &figure->vertices[next];
+
+ d2d_bezier_split_cubic(p[0], p[1], p[2], p[3], t, &b[0], &b[1], NULL);
- figure->bezier_controls[inter->control_idx + control_offset] = q[0];
- if (!(d2d_figure_insert_bezier_control(figure, inter->control_idx + control_offset + 1, &q[1])))
- return FALSE;
- ++control_offset;
+ figure->bezier_controls[inter->control_idx + control_offset] = b[0].point1;
+ figure->bezier_controls[inter->control_idx + control_offset + 1] = b[0].point2;
+ c[0] = &b[1].point1;
+ c[1] = &b[1].point2;
+
+ if (!(d2d_figure_insert_bezier_controls(figure, inter->control_idx + control_offset + 2, 2, c)))
+ return FALSE;
+ control_offset += 2;
+
+ split_type = D2D_VERTEX_TYPE_SPLIT_CUBIC_BEZIER;
+ }
+ else
+ {
+ p[2] = &figure->vertices[next];
+
+ d2d_point_lerp(&q[0], p[0], p[1], t);
+ d2d_point_lerp(&q[1], p[1], p[2], t);
+
+ figure->bezier_controls[inter->control_idx + control_offset] = q[0];
+ if (!(d2d_figure_insert_bezier_control(figure, inter->control_idx + control_offset + 1, &q[1])))
+ return FALSE;
+ ++control_offset;
+
+ split_type = D2D_VERTEX_TYPE_SPLIT_QUAD_BEZIER;
+ }
if (!(d2d_figure_insert_vertex(figure, inter->vertex_idx + vertex_offset + 1, inter->p)))
return FALSE;
- figure->vertex_types[inter->vertex_idx + vertex_offset + 1] = D2D_VERTEX_TYPE_SPLIT_BEZIER;
+ figure->vertex_types[inter->vertex_idx + vertex_offset + 1] = split_type;
++vertex_offset;
}
@@ -1961,9 +2120,9 @@ static BOOL d2d_geometry_intersect_self(struct d2d_geometry *geometry)
for (idx_q.vertex_idx = 0; idx_q.vertex_idx < max_q; ++idx_q.vertex_idx)
{
type_q = figure_q->vertex_types[idx_q.vertex_idx];
- if (type_q == D2D_VERTEX_TYPE_BEZIER)
+ if (d2d_vertex_type_is_unsplit_bezier(type_q))
{
- if (type_p == D2D_VERTEX_TYPE_BEZIER)
+ if (d2d_vertex_type_is_unsplit_bezier(type_p))
{
if (!d2d_geometry_intersect_bezier_bezier(geometry, &intersections,
&idx_p, 0.0f, 1.0f, &idx_q, 0.0f, 1.0f))
@@ -1974,11 +2133,14 @@ static BOOL d2d_geometry_intersect_self(struct d2d_geometry *geometry)
if (!d2d_geometry_intersect_bezier_line(geometry, &intersections, &idx_q, &idx_p))
goto done;
}
- ++idx_q.control_idx;
+ if (type_q == D2D_VERTEX_TYPE_QUADRATIC_BEZIER)
+ ++idx_q.control_idx;
+ else if (type_q == D2D_VERTEX_TYPE_CUBIC_BEZIER)
+ idx_q.control_idx += 2;
}
else
{
- if (type_p == D2D_VERTEX_TYPE_BEZIER)
+ if (d2d_vertex_type_is_unsplit_bezier(type_p))
{
if (!d2d_geometry_intersect_bezier_line(geometry, &intersections, &idx_p, &idx_q))
goto done;
@@ -1991,8 +2153,10 @@ static BOOL d2d_geometry_intersect_self(struct d2d_geometry *geometry)
}
}
}
- if (type_p == D2D_VERTEX_TYPE_BEZIER)
+ if (type_p == D2D_VERTEX_TYPE_QUADRATIC_BEZIER)
++idx_p.control_idx;
+ else if (type_p == D2D_VERTEX_TYPE_CUBIC_BEZIER)
+ idx_p.control_idx += 2;
}
}
@@ -2328,7 +2492,7 @@ static BOOL d2d_geometry_add_figure_outline(struct d2d_geometry *geometry,
if (!i)
{
prev_type = figure->vertex_types[figure->vertex_count - 1];
- if (prev_type == D2D_VERTEX_TYPE_BEZIER)
+ if (d2d_vertex_type_is_unsplit_bezier(prev_type))
prev = &figure->bezier_controls[figure->bezier_control_count - 1];
else
prev = &figure->vertices[figure->vertex_count - 1];
@@ -2336,19 +2500,22 @@ static BOOL d2d_geometry_add_figure_outline(struct d2d_geometry *geometry,
else
{
prev_type = figure->vertex_types[i - 1];
- if (prev_type == D2D_VERTEX_TYPE_BEZIER)
+ if (d2d_vertex_type_is_unsplit_bezier(prev_type))
prev = &figure->bezier_controls[bezier_idx - 1];
else
prev = &figure->vertices[i - 1];
}
- if (type == D2D_VERTEX_TYPE_BEZIER)
+ if (d2d_vertex_type_is_unsplit_bezier(type))
next = &figure->bezier_controls[bezier_idx++];
else if (i == figure->vertex_count - 1)
next = &figure->vertices[0];
else
next = &figure->vertices[i + 1];
+ if (type == D2D_VERTEX_TYPE_CUBIC_BEZIER)
+ bezier_idx++;
+
if (figure_end == D2D1_FIGURE_END_CLOSED || (i && i < figure->vertex_count - 1))
{
D2D1_POINT_2F q_next, q_prev;
@@ -2372,15 +2539,23 @@ static BOOL d2d_geometry_add_figure_outline(struct d2d_geometry *geometry,
ERR("Failed to add line segment.\n");
return FALSE;
}
- else if (type == D2D_VERTEX_TYPE_BEZIER)
+ else if (d2d_vertex_type_is_unsplit_bezier(type))
{
const D2D1_POINT_2F *p2;
+ D2D1_POINT_2F tmp;
if (i == figure->vertex_count - 1)
p2 = &figure->vertices[0];
else
p2 = &figure->vertices[i + 1];
+ if (type == D2D_VERTEX_TYPE_CUBIC_BEZIER)
+ {
+ d2d_bezier_cubic_to_quad(p0, &figure->bezier_controls[bezier_idx - 2],
+ &figure->bezier_controls[bezier_idx - 1], p2, &tmp);
+ next = &tmp;
+ }
+
if (!d2d_geometry_outline_add_bezier_segment(geometry, p0, next, p2))
{
ERR("Failed to add bezier segment.\n");
@@ -2561,6 +2736,7 @@ static void STDMETHODCALLTYPE d2d_geometry_sink_AddBeziers(ID2D1GeometrySink *if
{
struct d2d_geometry *geometry = impl_from_ID2D1GeometrySink(iface);
struct d2d_figure *figure = &geometry->u.path.figures[geometry->u.path.figure_count - 1];
+ const D2D1_POINT_2F *c[2];
D2D1_POINT_2F p;
unsigned int i;
@@ -2581,12 +2757,15 @@ static void STDMETHODCALLTYPE d2d_geometry_sink_AddBeziers(ID2D1GeometrySink *if
p.y = (beziers[i].point1.y + beziers[i].point2.y) * 0.75f;
p.x -= (figure->vertices[figure->vertex_count - 1].x + beziers[i].point3.x) * 0.25f;
p.y -= (figure->vertices[figure->vertex_count - 1].y + beziers[i].point3.y) * 0.25f;
- figure->vertex_types[figure->vertex_count - 1] = D2D_VERTEX_TYPE_BEZIER;
+ figure->vertex_types[figure->vertex_count - 1] = D2D_VERTEX_TYPE_CUBIC_BEZIER;
d2d_rect_get_bezier_bounds(&bezier_bounds, &figure->vertices[figure->vertex_count - 1],
&p, &beziers[i].point3);
- if (!d2d_figure_add_bezier_control(figure, &p))
+ c[0] = &beziers[i].point1;
+ c[1] = &beziers[i].point2;
+
+ if (!d2d_figure_add_bezier_controls(figure, 2, c))
{
ERR("Failed to add bezier control.\n");
geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
@@ -2659,23 +2838,29 @@ static void d2d_path_geometry_free_figures(struct d2d_geometry *geometry)
static BOOL d2d_geometry_get_bezier_segment_idx(struct d2d_geometry *geometry, struct d2d_segment_idx *idx, BOOL next)
{
+ struct d2d_figure *figure = &geometry->u.path.figures[idx->figure_idx];
+ enum d2d_vertex_type type = figure->vertex_types[idx->vertex_idx];
+
if (next)
{
+ if (d2d_vertex_type_is_cubic_bezier(type))
+ ++idx->control_idx;
+
++idx->vertex_idx;
++idx->control_idx;
}
for (; idx->figure_idx < geometry->u.path.figure_count; ++idx->figure_idx, idx->vertex_idx = idx->control_idx = 0)
{
- struct d2d_figure *figure = &geometry->u.path.figures[idx->figure_idx];
+ figure = &geometry->u.path.figures[idx->figure_idx];
if (!figure->bezier_control_count || figure->flags & D2D_FIGURE_FLAG_HOLLOW)
continue;
for (; idx->vertex_idx < figure->vertex_count; ++idx->vertex_idx)
{
- if (figure->vertex_types[idx->vertex_idx] == D2D_VERTEX_TYPE_BEZIER
- || figure->vertex_types[idx->vertex_idx] == D2D_VERTEX_TYPE_SPLIT_BEZIER)
+ type = figure->vertex_types[idx->vertex_idx];
+ if (d2d_vertex_type_is_bezier(type))
return TRUE;
}
}
@@ -2700,25 +2885,48 @@ static BOOL d2d_geometry_check_bezier_overlap(struct d2d_geometry *geometry,
{
const D2D1_POINT_2F *a[3], *b[3], *p[2], *q;
const struct d2d_figure *figure;
- D2D1_POINT_2F v_q[3], v_p, v_qp;
+ D2D1_POINT_2F v_q[3], v_p, v_qp, tmp_p, tmp_q;
+ enum d2d_vertex_type type;
unsigned int i, j, score;
float det, t;
figure = &geometry->u.path.figures[idx_p->figure_idx];
+ type = figure->vertex_types[idx_p->vertex_idx];
a[0] = &figure->vertices[idx_p->vertex_idx];
- a[1] = &figure->bezier_controls[idx_p->control_idx];
if (idx_p->vertex_idx == figure->vertex_count - 1)
a[2] = &figure->vertices[0];
else
a[2] = &figure->vertices[idx_p->vertex_idx + 1];
+ if (d2d_vertex_type_is_cubic_bezier(type))
+ {
+ d2d_bezier_cubic_to_quad(a[0],
+ &figure->bezier_controls[idx_p->control_idx],
+ &figure->bezier_controls[idx_p->control_idx + 1],
+ a[2], &tmp_p);
+
+ a[1] = &tmp_p;
+ }
+ else
+ a[1] = &figure->bezier_controls[idx_p->control_idx];
figure = &geometry->u.path.figures[idx_q->figure_idx];
+ type = figure->vertex_types[idx_q->vertex_idx];
b[0] = &figure->vertices[idx_q->vertex_idx];
- b[1] = &figure->bezier_controls[idx_q->control_idx];
if (idx_q->vertex_idx == figure->vertex_count - 1)
b[2] = &figure->vertices[0];
else
b[2] = &figure->vertices[idx_q->vertex_idx + 1];
+ if (d2d_vertex_type_is_cubic_bezier(type))
+ {
+ d2d_bezier_cubic_to_quad(b[0],
+ &figure->bezier_controls[idx_q->control_idx],
+ &figure->bezier_controls[idx_q->control_idx + 1],
+ b[2], &tmp_q);
+
+ b[1] = &tmp_q;
+ }
+ else
+ b[1] = &figure->bezier_controls[idx_q->control_idx];
if (d2d_point_ccw(a[0], a[1], a[2]) == 0.0f || d2d_point_ccw(b[0], b[1], b[2]) == 0.0f)
return FALSE;
@@ -2786,40 +2994,81 @@ static BOOL d2d_geometry_check_bezier_overlap(struct d2d_geometry *geometry,
static float d2d_geometry_bezier_ccw(struct d2d_geometry *geometry, const struct d2d_segment_idx *idx)
{
const struct d2d_figure *figure = &geometry->u.path.figures[idx->figure_idx];
+ enum d2d_vertex_type type = figure->vertex_types[idx->vertex_idx];
size_t next = idx->vertex_idx + 1;
+ const D2D1_POINT_2F *p;
+ D2D1_POINT_2F tmp;
if (next == figure->vertex_count)
next = 0;
- return d2d_point_ccw(&figure->vertices[idx->vertex_idx],
- &figure->bezier_controls[idx->control_idx], &figure->vertices[next]);
+ if (d2d_vertex_type_is_cubic_bezier(type))
+ {
+ d2d_bezier_cubic_to_quad(&figure->vertices[idx->vertex_idx],
+ &figure->bezier_controls[idx->control_idx],
+ &figure->bezier_controls[idx->control_idx + 1],
+ &figure->vertices[next], &tmp);
+
+ p = &tmp;
+ }
+ else
+ p = &figure->bezier_controls[idx->control_idx];
+
+ return d2d_point_ccw(&figure->vertices[idx->vertex_idx], p, &figure->vertices[next]);
}
static BOOL d2d_geometry_split_bezier(struct d2d_geometry *geometry, const struct d2d_segment_idx *idx)
{
- const D2D1_POINT_2F *p[3];
+ const D2D1_POINT_2F *p[4], *c[2];
struct d2d_figure *figure;
- D2D1_POINT_2F q[3];
+ enum d2d_vertex_type type;
+ D2D1_BEZIER_SEGMENT b[2];
+ D2D1_POINT_2F q[2], mid;
size_t next;
figure = &geometry->u.path.figures[idx->figure_idx];
+ type = figure->vertex_types[idx->vertex_idx];
p[0] = &figure->vertices[idx->vertex_idx];
p[1] = &figure->bezier_controls[idx->control_idx];
next = idx->vertex_idx + 1;
if (next == figure->vertex_count)
next = 0;
- p[2] = &figure->vertices[next];
- d2d_point_lerp(&q[0], p[0], p[1], 0.5f);
- d2d_point_lerp(&q[1], p[1], p[2], 0.5f);
- d2d_point_lerp(&q[2], &q[0], &q[1], 0.5f);
+ if (d2d_vertex_type_is_cubic_bezier(type))
+ {
+ p[2] = &figure->bezier_controls[idx->control_idx + 1];
+ p[3] = &figure->vertices[next];
- figure->bezier_controls[idx->control_idx] = q[0];
- if (!(d2d_figure_insert_bezier_control(figure, idx->control_idx + 1, &q[1])))
- return FALSE;
- if (!(d2d_figure_insert_vertex(figure, idx->vertex_idx + 1, q[2])))
+ d2d_bezier_split_cubic(p[0], p[1], p[2], p[3], 0.5f, &b[0], &b[1], &mid);
+
+ figure->bezier_controls[idx->control_idx] = b[0].point1;
+ figure->bezier_controls[idx->control_idx + 1] = b[0].point2;
+ c[0] = &b[1].point1;
+ c[1] = &b[1].point2;
+
+ if (!(d2d_figure_insert_bezier_controls(figure, idx->control_idx + 2, 2, c)))
+ return FALSE;
+
+ type = D2D_VERTEX_TYPE_SPLIT_CUBIC_BEZIER;
+ }
+ else
+ {
+ p[2] = &figure->vertices[next];
+
+ d2d_point_lerp(&q[0], p[0], p[1], 0.5f);
+ d2d_point_lerp(&q[1], p[1], p[2], 0.5f);
+ d2d_point_lerp(&mid, &q[0], &q[1], 0.5f);
+
+ figure->bezier_controls[idx->control_idx] = q[0];
+ if (!(d2d_figure_insert_bezier_control(figure, idx->control_idx + 1, &q[1])))
+ return FALSE;
+
+ type = D2D_VERTEX_TYPE_SPLIT_QUAD_BEZIER;
+ }
+
+ if (!(d2d_figure_insert_vertex(figure, idx->vertex_idx + 1, mid)))
return FALSE;
- figure->vertex_types[idx->vertex_idx + 1] = D2D_VERTEX_TYPE_SPLIT_BEZIER;
+ figure->vertex_types[idx->vertex_idx + 1] = type;
return TRUE;
}
@@ -2831,6 +3080,7 @@ static HRESULT d2d_geometry_resolve_beziers(struct d2d_geometry *geometry)
const D2D1_POINT_2F *p[3];
struct d2d_figure *figure;
size_t bezier_idx, i;
+ D2D1_POINT_2F tmp;
if (!d2d_geometry_get_first_bezier_segment_idx(geometry, &idx_p))
return S_OK;
@@ -2838,6 +3088,8 @@ static HRESULT d2d_geometry_resolve_beziers(struct d2d_geometry *geometry)
/* Split overlapping bezier control triangles. */
while (d2d_geometry_get_next_bezier_segment_idx(geometry, &idx_p))
{
+ figure = &geometry->u.path.figures[idx_p.figure_idx];
+
d2d_geometry_get_first_bezier_segment_idx(geometry, &idx_q);
while (idx_q.figure_idx < idx_p.figure_idx || idx_q.vertex_idx < idx_p.vertex_idx)
{
@@ -2849,6 +3101,9 @@ static HRESULT d2d_geometry_resolve_beziers(struct d2d_geometry *geometry)
return E_OUTOFMEMORY;
if (idx_p.figure_idx == idx_q.figure_idx)
{
+ if (d2d_vertex_type_is_cubic_bezier(figure->vertex_types[idx_p.vertex_idx]))
+ ++idx_p.control_idx;
+
++idx_p.vertex_idx;
++idx_p.control_idx;
}
@@ -2865,9 +3120,11 @@ static HRESULT d2d_geometry_resolve_beziers(struct d2d_geometry *geometry)
for (i = 0; i < geometry->u.path.figure_count; ++i)
{
- if (geometry->u.path.figures[i].flags & D2D_FIGURE_FLAG_HOLLOW)
+ figure = &geometry->u.path.figures[i];
+ if (figure->flags & D2D_FIGURE_FLAG_HOLLOW)
continue;
- geometry->fill.bezier_vertex_count += 3 * geometry->u.path.figures[i].bezier_control_count;
+
+ geometry->fill.bezier_vertex_count += 3 * d2d_figure_get_bezier_control_count(figure);
}
if (!(geometry->fill.bezier_vertices = heap_calloc(geometry->fill.bezier_vertex_count,
@@ -2886,9 +3143,23 @@ static HRESULT d2d_geometry_resolve_beziers(struct d2d_geometry *geometry)
figure = &geometry->u.path.figures[idx_p.figure_idx];
p[0] = &figure->vertices[idx_p.vertex_idx];
- p[1] = &figure->bezier_controls[idx_p.control_idx];
i = idx_p.vertex_idx + 1;
+ if (d2d_vertex_type_is_cubic_bezier(figure->vertex_types[idx_p.vertex_idx]))
+ {
+ if (i == figure->vertex_count)
+ p[2] = &figure->vertices[0];
+ else
+ p[2] = &figure->vertices[i];
+
+ d2d_bezier_cubic_to_quad(p[0], &figure->bezier_controls[idx_p.control_idx],
+ &figure->bezier_controls[idx_p.control_idx + 1], p[2], &tmp);
+
+ p[1] = &tmp;
+ }
+ else
+ p[1] = &figure->bezier_controls[idx_p.control_idx];
+
if (d2d_path_geometry_point_inside(geometry, p[1], FALSE))
{
sign = 1.0f;
@@ -3002,7 +3273,7 @@ static void STDMETHODCALLTYPE d2d_geometry_sink_AddQuadraticBeziers(ID2D1Geometr
d2d_rect_get_bezier_bounds(&bezier_bounds, &figure->vertices[figure->vertex_count - 1],
&beziers[i].point1, &beziers[i].point2);
- figure->vertex_types[figure->vertex_count - 1] = D2D_VERTEX_TYPE_BEZIER;
+ figure->vertex_types[figure->vertex_count - 1] = D2D_VERTEX_TYPE_QUADRATIC_BEZIER;
if (!d2d_figure_add_bezier_control(figure, &beziers[i].point1))
{
ERR("Failed to add bezier.\n");
@@ -3198,7 +3469,7 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_GetBounds(ID2D1PathGeometry *
for (bezier_idx = 0, ++j; j < figure->vertex_count; ++j)
{
if (figure->vertex_types[j] == D2D_VERTEX_TYPE_NONE
- || figure->vertex_types[j] == D2D_VERTEX_TYPE_SPLIT_BEZIER)
+ || d2d_vertex_type_is_split_bezier(figure->vertex_types[j]))
continue;
switch (type)
@@ -3209,7 +3480,7 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_GetBounds(ID2D1PathGeometry *
d2d_rect_expand(bounds, &p);
break;
- case D2D_VERTEX_TYPE_BEZIER:
+ case D2D_VERTEX_TYPE_QUADRATIC_BEZIER:
p1 = figure->original_bezier_controls[bezier_idx++];
d2d_point_transform(&p1, transform, p1.x, p1.y);
p2 = figure->vertices[j];
@@ -3219,6 +3490,20 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_GetBounds(ID2D1PathGeometry *
p = p2;
break;
+ case D2D_VERTEX_TYPE_CUBIC_BEZIER:
+ d2d_bezier_cubic_to_quad(&figure->vertices[j - 1],
+ &figure->original_bezier_controls[bezier_idx],
+ &figure->original_bezier_controls[bezier_idx + 1],
+ &figure->vertices[j], &p1);
+ bezier_idx += 2;
+ d2d_point_transform(&p1, transform, p1.x, p1.y);
+ p2 = figure->vertices[j];
+ d2d_point_transform(&p2, transform, p2.x, p2.y);
+ d2d_rect_get_bezier_bounds(&bezier_bounds, &p, &p1, &p2);
+ d2d_rect_union(bounds, &bezier_bounds);
+ p = p2;
+ break;
+
default:
FIXME("Unhandled vertex type %#x.\n", type);
p = figure->vertices[j];
@@ -3230,9 +3515,20 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_GetBounds(ID2D1PathGeometry *
type = figure->vertex_types[j];
}
- if (type == D2D_VERTEX_TYPE_BEZIER)
+ if (d2d_vertex_type_is_unsplit_bezier(type))
{
- p1 = figure->original_bezier_controls[bezier_idx++];
+ if (type == D2D_VERTEX_TYPE_CUBIC_BEZIER)
+ {
+ d2d_bezier_cubic_to_quad(&figure->vertices[j - 1],
+ &figure->original_bezier_controls[bezier_idx],
+ &figure->original_bezier_controls[bezier_idx + 1],
+ &figure->vertices[0], &p1);
+
+ bezier_idx += 2;
+ }
+ else
+ p1 = figure->original_bezier_controls[bezier_idx++];
+
d2d_point_transform(&p1, transform, p1.x, p1.y);
p2 = figure->vertices[0];
d2d_point_transform(&p2, transform, p2.x, p2.y);
@@ -3365,6 +3661,23 @@ static void d2d_geometry_simplify_quadratic(ID2D1SimplifiedGeometrySink *sink,
ID2D1SimplifiedGeometrySink_AddBeziers(sink, &b, 1);
}
+static void d2d_geometry_simplify_cubic(ID2D1SimplifiedGeometrySink *sink,
+ D2D1_GEOMETRY_SIMPLIFICATION_OPTION option, const D2D1_POINT_2F *p0,
+ const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2, const D2D1_POINT_2F *p3,
+ float tolerance)
+{
+ D2D1_BEZIER_SEGMENT b;
+
+ b.point1 = *p1;
+ b.point2 = *p2;
+ b.point3 = *p3;
+
+ if (option == D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES)
+ d2d_geometry_flatten_cubic(sink, p0, &b, tolerance);
+ else
+ ID2D1SimplifiedGeometrySink_AddBeziers(sink, &b, 1);
+}
+
static HRESULT STDMETHODCALLTYPE d2d_path_geometry_Simplify(ID2D1PathGeometry *iface,
D2D1_GEOMETRY_SIMPLIFICATION_OPTION option, const D2D1_MATRIX_3X2_F *transform, float tolerance,
ID2D1SimplifiedGeometrySink *sink)
@@ -3373,7 +3686,7 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_Simplify(ID2D1PathGeometry *i
enum d2d_vertex_type type = D2D_VERTEX_TYPE_NONE;
unsigned int i, j, bezier_idx;
D2D1_FIGURE_BEGIN begin;
- D2D1_POINT_2F p, p1, p2;
+ D2D1_POINT_2F p, p1, p2, p3;
D2D1_FIGURE_END end;
TRACE("iface %p, option %#x, transform %p, tolerance %.8e, sink %p.\n",
@@ -3401,7 +3714,7 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_Simplify(ID2D1PathGeometry *i
for (bezier_idx = 0, ++j; j < figure->vertex_count; ++j)
{
if (figure->vertex_types[j] == D2D_VERTEX_TYPE_NONE
- || figure->vertex_types[j] == D2D_VERTEX_TYPE_SPLIT_BEZIER)
+ || d2d_vertex_type_is_split_bezier(figure->vertex_types[j]))
continue;
switch (type)
@@ -3413,7 +3726,7 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_Simplify(ID2D1PathGeometry *i
ID2D1SimplifiedGeometrySink_AddLines(sink, &p, 1);
break;
- case D2D_VERTEX_TYPE_BEZIER:
+ case D2D_VERTEX_TYPE_QUADRATIC_BEZIER:
p1 = figure->original_bezier_controls[bezier_idx++];
if (transform)
d2d_point_transform(&p1, transform, p1.x, p1.y);
@@ -3424,6 +3737,20 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_Simplify(ID2D1PathGeometry *i
p = p2;
break;
+ case D2D_VERTEX_TYPE_CUBIC_BEZIER:
+ p1 = figure->original_bezier_controls[bezier_idx++];
+ if (transform)
+ d2d_point_transform(&p1, transform, p1.x, p1.y);
+ p2 = figure->original_bezier_controls[bezier_idx++];
+ if (transform)
+ d2d_point_transform(&p2, transform, p2.x, p2.y);
+ p3 = figure->vertices[j];
+ if (transform)
+ d2d_point_transform(&p3, transform, p3.x, p3.y);
+ d2d_geometry_simplify_cubic(sink, option, &p, &p1, &p2, &p3, tolerance);
+ p = p3;
+ break;
+
default:
FIXME("Unhandled vertex type %#x.\n", type);
p = figure->vertices[j];
@@ -3436,7 +3763,7 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_Simplify(ID2D1PathGeometry *i
type = figure->vertex_types[j];
}
- if (type == D2D_VERTEX_TYPE_BEZIER)
+ if (type == D2D_VERTEX_TYPE_QUADRATIC_BEZIER)
{
p1 = figure->original_bezier_controls[bezier_idx++];
if (transform)
@@ -3446,6 +3773,19 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_Simplify(ID2D1PathGeometry *i
d2d_point_transform(&p2, transform, p2.x, p2.y);
d2d_geometry_simplify_quadratic(sink, option, &p, &p1, &p2, tolerance);
}
+ else if (type == D2D_VERTEX_TYPE_CUBIC_BEZIER)
+ {
+ p1 = figure->original_bezier_controls[bezier_idx++];
+ if (transform)
+ d2d_point_transform(&p1, transform, p1.x, p1.y);
+ p2 = figure->original_bezier_controls[bezier_idx++];
+ if (transform)
+ d2d_point_transform(&p2, transform, p2.x, p2.y);
+ p3 = figure->vertices[0];
+ if (transform)
+ d2d_point_transform(&p3, transform, p3.x, p3.y);
+ d2d_geometry_simplify_cubic(sink, option, &p, &p1, &p2, &p3, tolerance);
+ }
end = figure->flags & D2D_FIGURE_FLAG_CLOSED ? D2D1_FIGURE_END_CLOSED : D2D1_FIGURE_END_OPEN;
ID2D1SimplifiedGeometrySink_EndFigure(sink, end);
--
2.20.1
3
9
[PATCH] dlls/dxgi: Implement IDXGIFactory5::CheckFeatureSupport.
by Hans-Kristian Arntzen 02 Apr '20
by Hans-Kristian Arntzen 02 Apr '20
02 Apr '20
Enables certain D3D12 games to use sync off, since they gate their use
of swap_interval == 0 on this feature being present.
Signed-off-by: Hans-Kristian Arntzen <post(a)arntzen-software.no>
---
dlls/dxgi/factory.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/dlls/dxgi/factory.c b/dlls/dxgi/factory.c
index 3f41df9e36..62148adf20 100644
--- a/dlls/dxgi/factory.c
+++ b/dlls/dxgi/factory.c
@@ -445,10 +445,21 @@ static HRESULT STDMETHODCALLTYPE dxgi_factory_EnumWarpAdapter(IWineDXGIFactory *
static HRESULT STDMETHODCALLTYPE dxgi_factory_CheckFeatureSupport(IWineDXGIFactory *iface,
DXGI_FEATURE feature, void *feature_data, UINT data_size)
{
- FIXME("iface %p, feature %#x, feature_data %p, data_size %u stub!\n",
+ TRACE("iface %p, feature %#x, feature_data %p, data_size %u.\n",
iface, feature, feature_data, data_size);
- return E_NOTIMPL;
+ if (feature == DXGI_FEATURE_PRESENT_ALLOW_TEARING)
+ {
+ if (data_size == sizeof(BOOL))
+ {
+ *(BOOL *)feature_data = TRUE;
+ return S_OK;
+ }
+ else
+ return DXGI_ERROR_INVALID_CALL;
+ }
+ else
+ return DXGI_ERROR_UNSUPPORTED;
}
static const struct IWineDXGIFactoryVtbl dxgi_factory_vtbl =
--
2.26.0
3
3
Hi all!
I have been playing with fuse-overlayfs [1] lately to reduce prefix size
and speed up wine startup time, and I thought maybe someone else could
be interested, and I would definitely be interested in some feedback,
especially if anyone already tried.
So far it has been working good for me, but to be fair I haven't used it
extensively yet. To enable the overlays, define the WINEPREFIX_OVERLAYS
environment variable to point to one or more drive_c to stack under
the prefix's drive_c, from top to bottom. For instance, creating a new
layered prefix with an existing default prefix and an additional
intermediate layer:
WINEPREFIX_OVERLAYS=$PWD/pfx_layer1/drive_c:$PWD/default_pfx/drive_c \
WINEPREFIX=$PWD/.wine \
wine winecfg
Another possible advantage is that it makes it immediately clear which
files were modified by an application, as only these files will reside
in the upper layer.
Then there's a few drawbacks with this approach, notably prefix updates
becomes a bit complicated. The file updates aren't a real issue, and
it's actually very fitting for that, as the lower-most dir would
probably be a default wine prefix with all the builtin libraries, and
the upper dir contain only custom installed dlls. But the registry
updates on the other hand are more tricky as the registry backing files
quickly gets modified and copied to the upper dir.
For now I just disabled prefix updates when overlays are used, for
simplicity. I have a few ideas on how to do that properly but I didn't
implement anything yet.
Also, for simplicity only drive_c is currently overlayed, and I moved
wine-specific files under it. Having the whole prefix mounted creates
additional trouble as we use the prefix directory inode and dev numbers
for server identification, and having a mount here changes the values
after the initial server startup.
Cheers,
[1] https://github.com/containers/fuse-overlayfs
* OverlayFS is a file system concept with a set of "lower" read-only
directories layered under an "upper" read-write directory. The lower
dirs files are copied-on-write to the "upper" directory.
* fuse-overlayfs is a FUSE implementation of overlayfs so that it's
possible for a unpriviledged user to mount such a filesystem. It's
available on most linux distros as far as I know.
Rémi Bernon (5):
server: Move registry files to drive_c/.wine.
wineboot: Move .update-timestamp to drive_c/.wine.
wineboot: Open update-timestamp read-only first.
wineboot: Disable prefix update if overlays are used.
server: Support mounting a FUSE overlayfs on drive_c.
programs/wineboot/wineboot.c | 39 ++++++++++++--------
server/main.c | 71 ++++++++++++++++++++++++++++++++++++
server/registry.c | 13 +++++--
3 files changed, 104 insertions(+), 19 deletions(-)
--
2.26.0.rc2
5
11
01 Apr '20
From: Zebediah Figura <zfigura(a)codeweavers.com>
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/d3dcompiler_43/d3dcompiler_private.h | 2 +
dlls/d3dcompiler_43/hlsl.y | 65 ++++++++++++++++++++---
dlls/d3dcompiler_43/utils.c | 2 +-
3 files changed, 62 insertions(+), 7 deletions(-)
diff --git a/dlls/d3dcompiler_43/d3dcompiler_private.h b/dlls/d3dcompiler_43/d3dcompiler_private.h
index 2a926282128..0dee4129f01 100644
--- a/dlls/d3dcompiler_43/d3dcompiler_private.h
+++ b/dlls/d3dcompiler_43/d3dcompiler_private.h
@@ -658,6 +658,7 @@ struct hlsl_ir_node
{
struct list entry;
enum hlsl_ir_node_type type;
+ unsigned int index; /* for liveness ranges */
struct hlsl_type *data_type;
struct source_location loc;
@@ -734,6 +735,7 @@ struct hlsl_ir_loop
struct hlsl_ir_node node;
/* loop condition is stored in the body (as "if (!condition) break;") */
struct list *body;
+ unsigned int next_index; /* liveness index of the end of the loop */
};
enum hlsl_ir_expr_op {
diff --git a/dlls/d3dcompiler_43/hlsl.y b/dlls/d3dcompiler_43/hlsl.y
index 4c3e96caa0d..bf1704b5d55 100644
--- a/dlls/d3dcompiler_43/hlsl.y
+++ b/dlls/d3dcompiler_43/hlsl.y
@@ -915,6 +915,19 @@ static const struct hlsl_ir_function_decl *get_overloaded_func(struct wine_rb_tr
return NULL;
}
+static struct hlsl_ir_function_decl *get_func_entry(const char *name)
+{
+ struct wine_rb_entry *entry;
+
+ if ((entry = wine_rb_get(&hlsl_ctx.functions, name))
+ && (entry = WINE_RB_ENTRY_VALUE(entry, struct hlsl_ir_function, entry)->overloads.root))
+ {
+ return WINE_RB_ENTRY_VALUE(entry, struct hlsl_ir_function_decl, entry);
+ }
+
+ return NULL;
+}
+
static struct list *append_unop(struct list *list, struct hlsl_ir_node *node)
{
list_add_tail(list, &node->entry);
@@ -2545,9 +2558,37 @@ static void dump_function(struct wine_rb_entry *entry, void *context)
wine_rb_for_each_entry(&func->overloads, dump_function_decl, NULL);
}
+/* Allocate a unique, ordered index to each instruction, which will be used for
+ * computing liveness ranges. */
+static unsigned int index_instructions(struct list *instrs, unsigned int index)
+{
+ struct hlsl_ir_node *instr;
+
+ LIST_FOR_EACH_ENTRY(instr, instrs, struct hlsl_ir_node, entry)
+ {
+ instr->index = index++;
+
+ if (instr->type == HLSL_IR_IF)
+ {
+ struct hlsl_ir_if *iff = if_from_node(instr);
+ index = index_instructions(iff->then_instrs, index);
+ if (iff->else_instrs)
+ index = index_instructions(iff->else_instrs, index);
+ }
+ else if (instr->type == HLSL_IR_LOOP)
+ {
+ index = index_instructions(loop_from_node(instr)->body, index);
+ loop_from_node(instr)->next_index = index;
+ }
+ }
+
+ return index;
+}
+
struct bwriter_shader *parse_hlsl(enum shader_type type, DWORD major, DWORD minor,
const char *entrypoint, char **messages)
{
+ struct hlsl_ir_function_decl *entry_func;
struct hlsl_scope *scope, *next_scope;
struct hlsl_type *hlsl_type, *next_type;
struct hlsl_ir_var *var, *next_var;
@@ -2573,12 +2614,6 @@ struct bwriter_shader *parse_hlsl(enum shader_type type, DWORD major, DWORD mino
hlsl_parse();
- if (TRACE_ON(hlsl_parser))
- {
- TRACE("IR dump.\n");
- wine_rb_for_each_entry(&hlsl_ctx.functions, dump_function, NULL);
- }
-
TRACE("Compilation status = %d\n", hlsl_ctx.status);
if (messages)
{
@@ -2597,6 +2632,24 @@ struct bwriter_shader *parse_hlsl(enum shader_type type, DWORD major, DWORD mino
d3dcompiler_free((void *)hlsl_ctx.source_files[i]);
d3dcompiler_free(hlsl_ctx.source_files);
+ if (hlsl_ctx.status == PARSE_ERR)
+ goto out;
+
+ if (!(entry_func = get_func_entry(entrypoint)))
+ {
+ hlsl_message("error: entry point %s is not defined\n", debugstr_a(entrypoint));
+ goto out;
+ }
+
+ index_instructions(entry_func->body, 1);
+
+ if (TRACE_ON(hlsl_parser))
+ {
+ TRACE("IR dump.\n");
+ wine_rb_for_each_entry(&hlsl_ctx.functions, dump_function, NULL);
+ }
+
+out:
TRACE("Freeing functions IR.\n");
wine_rb_destroy(&hlsl_ctx.functions, free_function_rb, NULL);
diff --git a/dlls/d3dcompiler_43/utils.c b/dlls/d3dcompiler_43/utils.c
index 6e9bb593e00..84323c334f8 100644
--- a/dlls/d3dcompiler_43/utils.c
+++ b/dlls/d3dcompiler_43/utils.c
@@ -2156,7 +2156,7 @@ static void debug_dump_ir_loop(const struct hlsl_ir_loop *loop)
static void debug_dump_instr(const struct hlsl_ir_node *instr)
{
- wine_dbg_printf("%p: ", instr);
+ wine_dbg_printf("%4u: %p: ", instr->index, instr);
switch (instr->type)
{
case HLSL_IR_EXPR:
--
2.25.1
4
18
[PATCH v4 1/5] d3dx9: Add a helper for computing the bounding rectangle in ID3DXFont_DrawText.
by Sven Baars 01 Apr '20
by Sven Baars 01 Apr '20
01 Apr '20
Signed-off-by: Sven Baars <sbaars(a)codeweavers.com>
---
v4: New patch
dlls/d3dx9_36/font.c | 153 +++++++++++++++++++++++++------------------
1 file changed, 90 insertions(+), 63 deletions(-)
diff --git a/dlls/d3dx9_36/font.c b/dlls/d3dx9_36/font.c
index 54b1574bb1..47d44a914e 100644
--- a/dlls/d3dx9_36/font.c
+++ b/dlls/d3dx9_36/font.c
@@ -599,16 +599,44 @@ static const WCHAR *read_line(HDC hdc, const WCHAR *str, int *count,
return NULL;
}
+static int compute_rect(struct d3dx_font *font, const WCHAR *string, INT count, WCHAR *line, RECT *rect, DWORD format)
+{
+ int y, lh, width, top = rect->top;
+ int max_width = 0;
+ SIZE size;
+
+ y = rect->top;
+ lh = font->metrics.tmHeight;
+ width = rect->right - rect->left;
+
+ while (string)
+ {
+ unsigned int line_len;
+
+ string = read_line(font->hdc, string, &count, line, &line_len, width, format, &size);
+
+ if (size.cx > max_width)
+ max_width = size.cx;
+
+ y += lh;
+ if (!(format & DT_NOCLIP) && (y > rect->bottom))
+ break;
+ }
+
+ rect->right = rect->left + max_width;
+ rect->bottom = y;
+
+ return rect->bottom - top;
+}
+
static INT WINAPI ID3DXFontImpl_DrawTextW(ID3DXFont *iface, ID3DXSprite *sprite,
const WCHAR *string, INT count, RECT *rect, DWORD format, D3DCOLOR color)
{
struct d3dx_font *font = impl_from_ID3DXFont(iface);
+ int lh, x, y, width, top, ret = 0;
ID3DXSprite *target = sprite;
+ RECT r = {0};
WCHAR *line;
- RECT textrect = {0};
- int lh, x, y, width;
- int max_width = 0;
- int ret = 0;
SIZE size;
TRACE("iface %p, sprite %p, string %s, count %d, rect %s, format %#x, color 0x%08x.\n",
@@ -629,20 +657,36 @@ static INT WINAPI ID3DXFontImpl_DrawTextW(ID3DXFont *iface, ID3DXSprite *sprite,
if (format & DT_SINGLELINE)
format &= ~DT_WORDBREAK;
- if (rect)
- textrect = *rect;
-
- x = textrect.left;
- y = textrect.top;
- width = textrect.right - textrect.left;
-
- lh = font->metrics.tmHeight;
-
line = heap_alloc(count * sizeof(*line));
if (!line)
return 0;
- if (!(format & DT_CALCRECT) && !sprite)
+ if (!rect || format & DT_CALCRECT)
+ {
+ if (!rect)
+ {
+ rect = &r;
+ format |= DT_NOCLIP;
+ }
+
+ top = rect->top;
+
+ ret = compute_rect(font, string, count, line, rect, format);
+
+ if (format & DT_CALCRECT)
+ goto cleanup;
+ }
+ else
+ {
+ top = rect->top;
+ }
+
+ x = rect->left;
+ y = rect->top;
+ lh = font->metrics.tmHeight;
+ width = rect->right - rect->left;
+
+ if (!sprite)
{
D3DXCreateSprite(font->device, &target);
ID3DXSprite_Begin(target, 0);
@@ -650,72 +694,55 @@ static INT WINAPI ID3DXFontImpl_DrawTextW(ID3DXFont *iface, ID3DXSprite *sprite,
while (string)
{
- unsigned int line_len;
+ unsigned int line_len, i;
+ GCP_RESULTSW results;
+ D3DXVECTOR3 pos;
string = read_line(font->hdc, string, &count, line, &line_len, width, format, &size);
- if (!(format & DT_CALCRECT))
- {
- GCP_RESULTSW results;
- D3DXVECTOR3 pos;
- unsigned int i;
-
- memset(&results, 0, sizeof(results));
- results.nGlyphs = line_len;
+ memset(&results, 0, sizeof(results));
+ results.nGlyphs = line_len;
- results.lpCaretPos = heap_alloc(line_len * sizeof(*results.lpCaretPos));
- if (!results.lpCaretPos)
- goto cleanup;
+ results.lpCaretPos = heap_alloc(line_len * sizeof(*results.lpCaretPos));
+ if (!results.lpCaretPos)
+ goto cleanup;
- results.lpGlyphs = heap_alloc(line_len * sizeof(*results.lpGlyphs));
- if (!results.lpGlyphs)
- {
- heap_free(results.lpCaretPos);
- goto cleanup;
- }
-
- GetCharacterPlacementW(font->hdc, line, line_len, 0, &results, 0);
+ results.lpGlyphs = heap_alloc(line_len * sizeof(*results.lpGlyphs));
+ if (!results.lpGlyphs)
+ {
+ heap_free(results.lpCaretPos);
+ goto cleanup;
+ }
- for (i = 0; i < results.nGlyphs; ++i)
- {
- IDirect3DTexture9 *texture;
- POINT cell_inc;
- RECT black_box;
+ GetCharacterPlacementW(font->hdc, line, line_len, 0, &results, 0);
- ID3DXFont_GetGlyphData(iface, results.lpGlyphs[i], &texture, &black_box, &cell_inc);
+ for (i = 0; i < results.nGlyphs; ++i)
+ {
+ IDirect3DTexture9 *texture;
+ POINT cell_inc;
+ RECT black_box;
- if (!texture)
- continue;
+ ID3DXFont_GetGlyphData(iface, results.lpGlyphs[i], &texture, &black_box, &cell_inc);
- pos.x = cell_inc.x + x + results.lpCaretPos[i];
- pos.y = cell_inc.y + y;
+ if (!texture)
+ continue;
- ID3DXSprite_Draw(target, texture, &black_box, NULL, &pos, color);
- IDirect3DTexture9_Release(texture);
- }
+ pos.x = cell_inc.x + x + results.lpCaretPos[i];
+ pos.y = cell_inc.y + y;
- heap_free(results.lpCaretPos);
- heap_free(results.lpGlyphs);
- }
- else if (size.cx > max_width)
- {
- max_width = size.cx;
+ ID3DXSprite_Draw(target, texture, &black_box, NULL, &pos, color);
+ IDirect3DTexture9_Release(texture);
}
+ heap_free(results.lpCaretPos);
+ heap_free(results.lpGlyphs);
+
y += lh;
- if (!(DT_NOCLIP & format) && (y > textrect.bottom))
+ if (!(DT_NOCLIP & format) && (y > rect->bottom))
break;
}
- if (format & DT_CALCRECT && rect)
- {
- *rect = textrect;
-
- rect->bottom = y;
- rect->right = rect->left + max_width;
- }
-
- ret = y - textrect.top;
+ ret = y - top;
cleanup:
if (target != sprite)
--
2.24.0
3
7
01 Apr '20
Signed-off-by: Fabian Maurer <dark.shadow4(a)web.de>
---
v3: Fix test error
v4: Add test for being unable to open file
---
programs/find/tests/find.c | 51 ++++++++++++++++++++++++++++++++++++++
1 file changed, 51 insertions(+)
diff --git a/programs/find/tests/find.c b/programs/find/tests/find.c
index b8345034b5..a15b5d2966 100644
--- a/programs/find/tests/find.c
+++ b/programs/find/tests/find.c
@@ -264,6 +264,56 @@ static void run_find_unicode_(const BYTE *input, int input_len, const BYTE *out_
run_find_stdin_(wstr_quoted_test, input, input_len, out_expected_mangled, out_expected_mangled_len, exitcode_expected, file, line);
}
+static void run_find_file_multi(void)
+{
+ char path_temp_file1[MAX_PATH];
+ char path_temp_file2[MAX_PATH];
+ char path_temp_file3[MAX_PATH];
+ char path_temp_dir[MAX_PATH];
+ HANDLE handle_file;
+ WCHAR commandline_new[MAX_PATH];
+ char out_expected[500];
+ const char* input = "ab\nbd";
+
+ GetTempPathA(ARRAY_SIZE(path_temp_dir), path_temp_dir);
+ GetTempFileNameA(path_temp_dir, "", 0, path_temp_file1);
+ GetTempFileNameA(path_temp_dir, "", 0, path_temp_file2);
+ GetTempFileNameA(path_temp_dir, "", 0, path_temp_file3);
+ handle_file = CreateFileA(path_temp_file1, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+ write_to_handle(handle_file, (BYTE*)input, strlen(input));
+ CloseHandle(handle_file);
+ handle_file = CreateFileA(path_temp_file2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+ write_to_handle(handle_file, (BYTE*)input, strlen(input));
+ CloseHandle(handle_file);
+
+ wsprintfW(commandline_new, L"\"b\" C:\\doesnotexist1 %hs C:\\doesnotexist1 %hs C:\\doesnotexist1 %hs", path_temp_file1, path_temp_file2, path_temp_file3);
+
+ /* Keep file open during the test */
+ handle_file = CreateFileA(path_temp_file3, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+
+ CharUpperA(path_temp_file1);
+ CharUpperA(path_temp_file2);
+ CharUpperA(path_temp_file3);
+ wsprintfA(out_expected,
+ "File not found - C:\\DOESNOTEXIST1\r\n"
+ "\r\n---------- %s\r\n"
+ "ab\r\nbd\r\n"
+ "File not found - C:\\DOESNOTEXIST1\r\n"
+ "\r\n---------- %s\r\n"
+ "ab\r\nbd\r\n"
+ "File not found - C:\\DOESNOTEXIST1\r\n"
+ "File not found - %s\r\n",
+ path_temp_file1, path_temp_file2, path_temp_file3);
+
+ todo_wine
+ run_find_stdin_(commandline_new, (BYTE*)"", 0, (BYTE*)out_expected, strlen(out_expected), 0, __FILE__, __LINE__);
+
+ CloseHandle(handle_file);
+ DeleteFileA(path_temp_file1);
+ DeleteFileA(path_temp_file2);
+ DeleteFileA(path_temp_file3);
+}
+
static void test_errors(void)
{
run_find_stdin_str("", "", "FIND: Parameter format not correct\r\n", 2);
@@ -411,6 +461,7 @@ START_TEST(find)
else
{
test_errors();
+ run_find_file_multi();
}
test_singleline_without_switches();
test_multiline();
--
2.25.1
1
2
[PATCH 4/4] qasf: Implement IFileSourceFilter_GetCurFile() for WM ASF reader.
by Jactry Zeng 01 Apr '20
by Jactry Zeng 01 Apr '20
01 Apr '20
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
dlls/qasf/tests/wmasf.c | 20 +++++++-------------
dlls/qasf/wmasf.c | 21 +++++++++++++++++++--
2 files changed, 26 insertions(+), 15 deletions(-)
diff --git a/dlls/qasf/tests/wmasf.c b/dlls/qasf/tests/wmasf.c
index 7cf11c6c9f..1620a24aa1 100644
--- a/dlls/qasf/tests/wmasf.c
+++ b/dlls/qasf/tests/wmasf.c
@@ -207,11 +207,11 @@ static void test_filesourcefilter(void)
olepath = (void *)0xdeadbeef;
memset(&type, 0x22, sizeof(type));
hr = IFileSourceFilter_GetCurFile(filesource, &olepath, &type);
- todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(!olepath, "Got %s.\n", wine_dbgstr_w(olepath));
- todo_wine ok(IsEqualGUID(&type.majortype, &MEDIATYPE_NULL), "Got majortype %s.\n",
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!olepath, "Got %s.\n", wine_dbgstr_w(olepath));
+ ok(IsEqualGUID(&type.majortype, &MEDIATYPE_NULL), "Got majortype %s.\n",
wine_dbgstr_guid(&type.majortype));
- todo_wine ok(IsEqualGUID(&type.subtype, &MEDIASUBTYPE_NULL), "Got subtype %s.\n",
+ ok(IsEqualGUID(&type.subtype, &MEDIASUBTYPE_NULL), "Got subtype %s.\n",
wine_dbgstr_guid(&type.subtype));
CoTaskMemFree(olepath);
@@ -219,7 +219,7 @@ static void test_filesourcefilter(void)
hr = IFileSourceFilter_Load(filesource, path, NULL);
ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = IFileSourceFilter_GetCurFile(filesource, NULL, NULL);
- todo_wine ok(hr == E_POINTER, "Got hr %#x.\n", hr);
+ ok(hr == E_POINTER, "Got hr %#x.\n", hr);
path = L"nonexistent2.wmv";
hr = IFileSourceFilter_Load(filesource, path, NULL);
@@ -229,16 +229,13 @@ static void test_filesourcefilter(void)
olepath = (void *)0xdeadbeef;
memset(&type, 0x22, sizeof(type));
hr = IFileSourceFilter_GetCurFile(filesource, &olepath, &type);
- todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
- if (SUCCEEDED(hr))
- {
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
ok(!wcscmp(olepath, path), "Expected path %s, got %s.\n",
wine_dbgstr_w(path), wine_dbgstr_w(olepath));
ok(IsEqualGUID(&type.majortype, &MEDIATYPE_NULL), "Got majortype %s.\n",
wine_dbgstr_guid(&type.majortype));
ok(IsEqualGUID(&type.subtype, &MEDIASUBTYPE_NULL), "Got subtype %s.\n",
wine_dbgstr_guid(&type.subtype));
- }
CoTaskMemFree(olepath);
hr = IFileSourceFilter_QueryInterface(filesource, &IID_IBaseFilter, (void **)&filter);
@@ -265,16 +262,13 @@ static void test_filesourcefilter(void)
olepath = (void *)0xdeadbeef;
memset(&type, 0x22, sizeof(type));
hr = IFileSourceFilter_GetCurFile(filesource, &olepath, &type);
- todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
- if (SUCCEEDED(hr))
- {
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
ok(!wcscmp(olepath, path), "Expected path %s, got %s.\n",
wine_dbgstr_w(path), wine_dbgstr_w(olepath));
ok(IsEqualGUID(&type.majortype, &MEDIATYPE_NULL), "Got majortype %s.\n",
wine_dbgstr_guid(&type.majortype));
ok(IsEqualGUID(&type.subtype, &MEDIASUBTYPE_NULL), "Got subtype %s.\n",
wine_dbgstr_guid(&type.subtype));
- }
CoTaskMemFree(olepath);
IFilterGraph2_Release(graph);
diff --git a/dlls/qasf/wmasf.c b/dlls/qasf/wmasf.c
index e8d1363170..4fc0726879 100644
--- a/dlls/qasf/wmasf.c
+++ b/dlls/qasf/wmasf.c
@@ -126,9 +126,26 @@ static HRESULT WINAPI filesourcefilter_Load(IFileSourceFilter * iface, LPCOLESTR
static HRESULT WINAPI filesourcefilter_GetCurFile(IFileSourceFilter *iface, LPOLESTR *filename, AM_MEDIA_TYPE *type)
{
- FIXME("(%p, %p, %p): stub.\n", iface, filename, type);
+ struct wmasf_reader *This = impl_reader_from_IFileSourceFilter(iface);
+
+ TRACE("(%p, %p, %p).\n", iface, filename, type);
+
+ if (!filename)
+ return E_POINTER;
+
+ *filename = NULL;
+ if (type)
+ memset(type, 0, sizeof(*type));
- return E_NOTIMPL;
+ if (This->filename)
+ {
+ *filename = CoTaskMemAlloc((wcslen(This->filename) + 1) * sizeof(WCHAR));
+ wcscpy(*filename, This->filename);
+ if (type)
+ CopyMediaType(type, &This->type);
+ }
+
+ return S_OK;
}
static const IFileSourceFilterVtbl filesourcefilter_vtbl =
--
2.26.0
3
2
[PATCH 3/4] qasf: Partially implement IFileSourceFilter_Load() for WM ASF reader.
by Jactry Zeng 01 Apr '20
by Jactry Zeng 01 Apr '20
01 Apr '20
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
dlls/qasf/tests/wmasf.c | 84 +++++++++++++++++++++++++++++++++++++++++
dlls/qasf/wmasf.c | 28 +++++++++++++-
2 files changed, 110 insertions(+), 2 deletions(-)
diff --git a/dlls/qasf/tests/wmasf.c b/dlls/qasf/tests/wmasf.c
index 3bf1e4ce4e..7cf11c6c9f 100644
--- a/dlls/qasf/tests/wmasf.c
+++ b/dlls/qasf/tests/wmasf.c
@@ -174,7 +174,13 @@ static void test_aggregation(void)
static void test_filesourcefilter(void)
{
IFileSourceFilter *filesource;
+ IFilterGraph2 *graph;
+ IEnumPins *enumpins;
IBaseFilter *filter;
+ AM_MEDIA_TYPE type;
+ const WCHAR *path;
+ LPOLESTR olepath;
+ IPin *pins[4];
HRESULT hr;
hr = CoCreateInstance(&CLSID_WMAsfReader, NULL, CLSCTX_INPROC_SERVER,
@@ -195,6 +201,84 @@ static void test_filesourcefilter(void)
ok(hr == S_OK, "Got hr %#x.\n", hr);
expected_ref(filesource, 1);
+ hr = IFileSourceFilter_Load(filesource, NULL, NULL);
+ ok(hr == E_POINTER, "Got hr %#x.\n", hr);
+
+ olepath = (void *)0xdeadbeef;
+ memset(&type, 0x22, sizeof(type));
+ hr = IFileSourceFilter_GetCurFile(filesource, &olepath, &type);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(!olepath, "Got %s.\n", wine_dbgstr_w(olepath));
+ todo_wine ok(IsEqualGUID(&type.majortype, &MEDIATYPE_NULL), "Got majortype %s.\n",
+ wine_dbgstr_guid(&type.majortype));
+ todo_wine ok(IsEqualGUID(&type.subtype, &MEDIASUBTYPE_NULL), "Got subtype %s.\n",
+ wine_dbgstr_guid(&type.subtype));
+ CoTaskMemFree(olepath);
+
+ path = L"nonexistent.wmv";
+ hr = IFileSourceFilter_Load(filesource, path, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IFileSourceFilter_GetCurFile(filesource, NULL, NULL);
+ todo_wine ok(hr == E_POINTER, "Got hr %#x.\n", hr);
+
+ path = L"nonexistent2.wmv";
+ hr = IFileSourceFilter_Load(filesource, path, NULL);
+ ok(hr == E_FAIL, "Got hr %#x.\n", hr);
+
+ path = L"nonexistent.wmv";
+ olepath = (void *)0xdeadbeef;
+ memset(&type, 0x22, sizeof(type));
+ hr = IFileSourceFilter_GetCurFile(filesource, &olepath, &type);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (SUCCEEDED(hr))
+ {
+ ok(!wcscmp(olepath, path), "Expected path %s, got %s.\n",
+ wine_dbgstr_w(path), wine_dbgstr_w(olepath));
+ ok(IsEqualGUID(&type.majortype, &MEDIATYPE_NULL), "Got majortype %s.\n",
+ wine_dbgstr_guid(&type.majortype));
+ ok(IsEqualGUID(&type.subtype, &MEDIASUBTYPE_NULL), "Got subtype %s.\n",
+ wine_dbgstr_guid(&type.subtype));
+ }
+ CoTaskMemFree(olepath);
+
+ hr = IFileSourceFilter_QueryInterface(filesource, &IID_IBaseFilter, (void **)&filter);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IBaseFilter_EnumPins(filter, &enumpins);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IEnumPins_Next(enumpins, 1, pins, NULL);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+ IEnumPins_Release(enumpins);
+
+ hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IFilterGraph2, (void **)&graph);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IFilterGraph2_AddFilter(graph, filter, NULL);
+ todo_wine ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
+ broken(hr == HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND)) /* win2008 */,
+ "Got hr %#x.\n", hr);
+
+ path = L"nonexistent2.wmv";
+ hr = IFileSourceFilter_Load(filesource, path, NULL);
+ ok(hr == E_FAIL, "Got hr %#x.\n", hr);
+
+ path = L"nonexistent.wmv";
+ olepath = (void *)0xdeadbeef;
+ memset(&type, 0x22, sizeof(type));
+ hr = IFileSourceFilter_GetCurFile(filesource, &olepath, &type);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (SUCCEEDED(hr))
+ {
+ ok(!wcscmp(olepath, path), "Expected path %s, got %s.\n",
+ wine_dbgstr_w(path), wine_dbgstr_w(olepath));
+ ok(IsEqualGUID(&type.majortype, &MEDIATYPE_NULL), "Got majortype %s.\n",
+ wine_dbgstr_guid(&type.majortype));
+ ok(IsEqualGUID(&type.subtype, &MEDIASUBTYPE_NULL), "Got subtype %s.\n",
+ wine_dbgstr_guid(&type.subtype));
+ }
+ CoTaskMemFree(olepath);
+
+ IFilterGraph2_Release(graph);
+ IBaseFilter_Release(filter);
IFileSourceFilter_Release(filesource);
}
diff --git a/dlls/qasf/wmasf.c b/dlls/qasf/wmasf.c
index ad7bb5be8f..e8d1363170 100644
--- a/dlls/qasf/wmasf.c
+++ b/dlls/qasf/wmasf.c
@@ -26,6 +26,9 @@ struct wmasf_reader
{
struct strmbase_filter filter;
IFileSourceFilter IFileSourceFilter_iface;
+
+ AM_MEDIA_TYPE type;
+ LPOLESTR filename;
};
static inline struct wmasf_reader *impl_reader_from_strmbase_filter(struct strmbase_filter *iface)
@@ -47,6 +50,12 @@ static void wmasf_reader_destroy(struct strmbase_filter *iface)
{
struct wmasf_reader *filter = impl_reader_from_strmbase_filter(iface);
+ if (filter->filename)
+ {
+ CoTaskMemFree(filter->filename);
+ FreeMediaType(&filter->type);
+ }
+
strmbase_filter_cleanup(&filter->filter);
free(filter);
}
@@ -95,9 +104,24 @@ static ULONG WINAPI filesourcefilter_Release(IFileSourceFilter *iface)
static HRESULT WINAPI filesourcefilter_Load(IFileSourceFilter * iface, LPCOLESTR filename, const AM_MEDIA_TYPE *type)
{
- FIXME("(%p, %s, %p): stub.\n", iface, debugstr_w(filename), type);
+ struct wmasf_reader *This = impl_reader_from_IFileSourceFilter(iface);
+ static const AM_MEDIA_TYPE empty_type = {0};
- return E_NOTIMPL;
+ TRACE("(%p, %s, %p).\n", iface, debugstr_w(filename), type);
+
+ if (!filename)
+ return E_POINTER;
+
+ if (This->filename)
+ return E_FAIL;
+
+ This->filename = wcsdup(filename);
+ if (!This->filename)
+ return E_OUTOFMEMORY;
+
+ CopyMediaType(&This->type, type ? type : &empty_type);
+
+ return S_OK;
}
static HRESULT WINAPI filesourcefilter_GetCurFile(IFileSourceFilter *iface, LPOLESTR *filename, AM_MEDIA_TYPE *type)
--
2.26.0
4
3