Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
May 2020
- 79 participants
- 1536 messages
Re: [PATCH vkd3d] makefiles: Introduce CROSS_LDFLAGS.
by Chip Davis
May 29, 2020 2:36 AM, "Henri Verbeet" <hverbeet(a)gmail.com> wrote:
> On Fri, 29 May 2020 at 05:40, Chip Davis <cdavis(a)codeweavers.com> wrote:
>
>> This is used when cross-compiling tests.
>
> Not unless you set it; I.e., what is the use-case here?
Passing -fuse-ld=lld to the compiler.
Chip
May 29, 2020
Re: [PATCH 3/7] dwrite/tests: Enable glyph class tests on Wine.
by Marvin
Hi,
While running your changed tests, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at:
https://testbot.winehq.org/JobDetails.pl?Key=72474
Your paranoid android.
=== build (build log) ===
error: patch failed: dlls/dwrite/opentype.c:4491
error: patch failed: dlls/dwrite/opentype.c:3200
Task: Patch failed to apply
May 29, 2020
[PATCH 5/5] wined3d: Implement swapchains for the Vulkan adapter.
by Henri Verbeet
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/wined3d/adapter_vk.c | 13 +-
dlls/wined3d/swapchain.c | 613 ++++++++++++++++++++++++++++++++-
dlls/wined3d/wined3d_private.h | 24 +-
dlls/wined3d/wined3d_vk.h | 18 +-
4 files changed, 658 insertions(+), 10 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c
index cbde5d3683c..586be3751a0 100644
--- a/dlls/wined3d/adapter_vk.c
+++ b/dlls/wined3d/adapter_vk.c
@@ -421,6 +421,7 @@ vulkan_device_extensions[] =
{VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, ~0u},
{VK_KHR_MAINTENANCE1_EXTENSION_NAME, VK_API_VERSION_1_1},
{VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, VK_API_VERSION_1_1},
+ {VK_KHR_SWAPCHAIN_EXTENSION_NAME, ~0u},
};
static bool enable_vulkan_device_extensions(VkPhysicalDevice physical_device, uint32_t *extension_count,
@@ -1180,7 +1181,7 @@ static void adapter_vk_copy_bo_address(struct wined3d_context *context,
static HRESULT adapter_vk_create_swapchain(struct wined3d_device *device, struct wined3d_swapchain_desc *desc,
void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain)
{
- struct wined3d_swapchain *swapchain_vk;
+ struct wined3d_swapchain_vk *swapchain_vk;
HRESULT hr;
TRACE("device %p, desc %p, parent %p, parent_ops %p, swapchain %p.\n",
@@ -1197,15 +1198,17 @@ static HRESULT adapter_vk_create_swapchain(struct wined3d_device *device, struct
}
TRACE("Created swapchain %p.\n", swapchain_vk);
- *swapchain = swapchain_vk;
+ *swapchain = &swapchain_vk->s;
return hr;
}
static void adapter_vk_destroy_swapchain(struct wined3d_swapchain *swapchain)
{
- wined3d_swapchain_cleanup(swapchain);
- heap_free(swapchain);
+ struct wined3d_swapchain_vk *swapchain_vk = wined3d_swapchain_vk(swapchain);
+
+ wined3d_swapchain_vk_cleanup(swapchain_vk);
+ heap_free(swapchain_vk);
}
unsigned int wined3d_adapter_vk_get_memory_type_index(const struct wined3d_adapter_vk *adapter_vk,
@@ -1827,6 +1830,8 @@ static const struct
vulkan_instance_extensions[] =
{
{VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_API_VERSION_1_1, FALSE},
+ {VK_KHR_SURFACE_EXTENSION_NAME, ~0u, TRUE},
+ {VK_KHR_WIN32_SURFACE_EXTENSION_NAME, ~0u, TRUE},
};
static BOOL enable_vulkan_instance_extensions(uint32_t *extension_count,
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index 465ab08eb82..e23da1180c1 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -113,6 +113,45 @@ void wined3d_swapchain_gl_cleanup(struct wined3d_swapchain_gl *swapchain_gl)
}
}
+static void wined3d_swapchain_vk_destroy_vulkan_swapchain(struct wined3d_swapchain_vk *swapchain_vk)
+{
+ struct wined3d_device_vk *device_vk = wined3d_device_vk(swapchain_vk->s.device);
+ const struct wined3d_vk_info *vk_info;
+ unsigned int i;
+ VkResult vr;
+
+ TRACE("swapchain_vk %p.\n", swapchain_vk);
+
+ vk_info = &wined3d_adapter_vk(device_vk->d.adapter)->vk_info;
+
+ if ((vr = VK_CALL(vkQueueWaitIdle(device_vk->vk_queue))) < 0)
+ ERR("Failed to wait on queue, vr %s.\n", wined3d_debug_vkresult(vr));
+ heap_free(swapchain_vk->vk_images);
+ for (i = 0; i < swapchain_vk->image_count; ++i)
+ {
+ VK_CALL(vkDestroySemaphore(device_vk->vk_device, swapchain_vk->vk_semaphores[i].available, NULL));
+ VK_CALL(vkDestroySemaphore(device_vk->vk_device, swapchain_vk->vk_semaphores[i].presentable, NULL));
+ }
+ heap_free(swapchain_vk->vk_semaphores);
+ VK_CALL(vkDestroySwapchainKHR(device_vk->vk_device, swapchain_vk->vk_swapchain, NULL));
+ VK_CALL(vkDestroySurfaceKHR(vk_info->instance, swapchain_vk->vk_surface, NULL));
+}
+
+static void wined3d_swapchain_vk_destroy_object(void *object)
+{
+ wined3d_swapchain_vk_destroy_vulkan_swapchain(object);
+}
+
+void wined3d_swapchain_vk_cleanup(struct wined3d_swapchain_vk *swapchain_vk)
+{
+ struct wined3d_cs *cs = swapchain_vk->s.device->cs;
+
+ wined3d_cs_destroy_object(cs, wined3d_swapchain_vk_destroy_object, swapchain_vk);
+ wined3d_cs_finish(cs, WINED3D_CS_QUEUE_DEFAULT);
+
+ wined3d_swapchain_cleanup(&swapchain_vk->s);
+}
+
ULONG CDECL wined3d_swapchain_incref(struct wined3d_swapchain *swapchain)
{
ULONG refcount = InterlockedIncrement(&swapchain->ref);
@@ -551,10 +590,561 @@ static const struct wined3d_swapchain_ops swapchain_gl_ops =
swapchain_frontbuffer_updated,
};
+static bool wined3d_swapchain_vk_present_mode_supported(struct wined3d_swapchain_vk *swapchain_vk,
+ VkPresentModeKHR vk_present_mode)
+{
+ struct wined3d_device_vk *device_vk = wined3d_device_vk(swapchain_vk->s.device);
+ const struct wined3d_vk_info *vk_info;
+ struct wined3d_adapter_vk *adapter_vk;
+ VkPhysicalDevice vk_physical_device;
+ VkPresentModeKHR *vk_modes;
+ bool supported = false;
+ uint32_t count, i;
+ VkResult vr;
+
+ adapter_vk = wined3d_adapter_vk(device_vk->d.adapter);
+ vk_physical_device = adapter_vk->physical_device;
+ vk_info = &adapter_vk->vk_info;
+
+ if ((vr = VK_CALL(vkGetPhysicalDeviceSurfacePresentModesKHR(vk_physical_device,
+ swapchain_vk->vk_surface, &count, NULL))) < 0)
+ {
+ ERR("Failed to get supported present mode count, vr %s.\n", wined3d_debug_vkresult(vr));
+ return false;
+ }
+
+ if (!(vk_modes = heap_calloc(count, sizeof(*vk_modes))))
+ return false;
+
+ if ((vr = VK_CALL(vkGetPhysicalDeviceSurfacePresentModesKHR(vk_physical_device,
+ swapchain_vk->vk_surface, &count, vk_modes))) < 0)
+ {
+ ERR("Failed to get supported present modes, vr %s.\n", wined3d_debug_vkresult(vr));
+ goto done;
+ }
+
+ for (i = 0; i < count; ++i)
+ {
+ if (vk_modes[i] == vk_present_mode)
+ {
+ supported = true;
+ goto done;
+ }
+ }
+
+done:
+ heap_free(vk_modes);
+ return supported;
+}
+
+static VkFormat wined3d_swapchain_vk_select_vk_format(struct wined3d_swapchain_vk *swapchain_vk,
+ VkSurfaceKHR vk_surface)
+{
+ struct wined3d_device_vk *device_vk = wined3d_device_vk(swapchain_vk->s.device);
+ const struct wined3d_swapchain_desc *desc = &swapchain_vk->s.state.desc;
+ const struct wined3d_vk_info *vk_info;
+ struct wined3d_adapter_vk *adapter_vk;
+ const struct wined3d_format *format;
+ VkPhysicalDevice vk_physical_device;
+ VkSurfaceFormatKHR *vk_formats;
+ uint32_t format_count, i;
+ VkFormat vk_format;
+ VkResult vr;
+
+ adapter_vk = wined3d_adapter_vk(device_vk->d.adapter);
+ vk_physical_device = adapter_vk->physical_device;
+ vk_info = &adapter_vk->vk_info;
+
+ if ((format = wined3d_get_format(&adapter_vk->a, desc->backbuffer_format, WINED3D_BIND_RENDER_TARGET)))
+ vk_format = wined3d_format_vk(format)->vk_format;
+ else
+ vk_format = VK_FORMAT_B8G8R8A8_UNORM;
+
+ vr = VK_CALL(vkGetPhysicalDeviceSurfaceFormatsKHR(vk_physical_device, vk_surface, &format_count, NULL));
+ if (vr < 0 || !format_count)
+ {
+ WARN("Failed to get supported surface format count, vr %s.\n", wined3d_debug_vkresult(vr));
+ return VK_FORMAT_UNDEFINED;
+ }
+
+ if (!(vk_formats = heap_calloc(format_count, sizeof(*vk_formats))))
+ return VK_FORMAT_UNDEFINED;
+
+ if ((vr = VK_CALL(vkGetPhysicalDeviceSurfaceFormatsKHR(vk_physical_device,
+ vk_surface, &format_count, vk_formats))) < 0)
+ {
+ WARN("Failed to get supported surface formats, vr %s.\n", wined3d_debug_vkresult(vr));
+ heap_free(vk_formats);
+ return VK_FORMAT_UNDEFINED;
+ }
+
+ for (i = 0; i < format_count; ++i)
+ {
+ if (vk_formats[i].format == vk_format && vk_formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
+ break;
+ }
+ if (i == format_count)
+ {
+ /* Try to create a swapchain with format conversion. */
+ vk_format = VK_FORMAT_B8G8R8A8_UNORM;
+ WARN("Failed to find Vulkan swapchain format for %s.\n", debug_d3dformat(desc->backbuffer_format));
+ for (i = 0; i < format_count; ++i)
+ {
+ if (vk_formats[i].format == vk_format && vk_formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
+ break;
+ }
+ }
+ heap_free(vk_formats);
+ if (i == format_count)
+ {
+ FIXME("Failed to find Vulkan swapchain format for %s.\n", debug_d3dformat(desc->backbuffer_format));
+ return VK_FORMAT_UNDEFINED;
+ }
+
+ TRACE("Using Vulkan swapchain format %#x.\n", vk_format);
+
+ return vk_format;
+}
+
+static bool wined3d_swapchain_vk_create_vulkan_swapchain_images(struct wined3d_swapchain_vk *swapchain_vk,
+ VkSwapchainKHR vk_swapchain)
+{
+ struct wined3d_device_vk *device_vk = wined3d_device_vk(swapchain_vk->s.device);
+ const struct wined3d_vk_info *vk_info;
+ VkSemaphoreCreateInfo semaphore_info;
+ uint32_t image_count, i;
+ VkResult vr;
+
+ vk_info = &wined3d_adapter_vk(device_vk->d.adapter)->vk_info;
+
+ if ((vr = VK_CALL(vkGetSwapchainImagesKHR(device_vk->vk_device, vk_swapchain, &image_count, NULL))) < 0)
+ {
+ ERR("Failed to get image count, vr %s\n", wined3d_debug_vkresult(vr));
+ return false;
+ }
+
+ if (!(swapchain_vk->vk_images = heap_calloc(image_count, sizeof(*swapchain_vk->vk_images))))
+ {
+ ERR("Failed to allocate images array.\n");
+ return false;
+ }
+
+ if ((vr = VK_CALL(vkGetSwapchainImagesKHR(device_vk->vk_device,
+ vk_swapchain, &image_count, swapchain_vk->vk_images))) < 0)
+ {
+ ERR("Failed to get swapchain images, vr %s.\n", wined3d_debug_vkresult(vr));
+ heap_free(swapchain_vk->vk_images);
+ return false;
+ }
+
+ if (!(swapchain_vk->vk_semaphores = heap_calloc(image_count, sizeof(*swapchain_vk->vk_semaphores))))
+ {
+ ERR("Failed to allocate semaphores array.\n");
+ heap_free(swapchain_vk->vk_images);
+ return false;
+ }
+
+ semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+ semaphore_info.pNext = NULL;
+ semaphore_info.flags = 0;
+ for (i = 0; i < image_count; ++i)
+ {
+ if ((vr = VK_CALL(vkCreateSemaphore(device_vk->vk_device,
+ &semaphore_info, NULL, &swapchain_vk->vk_semaphores[i].available))) < 0)
+ {
+ ERR("Failed to create semaphore, vr %s.\n", wined3d_debug_vkresult(vr));
+ goto fail;
+ }
+
+ if ((vr = VK_CALL(vkCreateSemaphore(device_vk->vk_device,
+ &semaphore_info, NULL, &swapchain_vk->vk_semaphores[i].presentable))) < 0)
+ {
+ ERR("Failed to create semaphore, vr %s.\n", wined3d_debug_vkresult(vr));
+ goto fail;
+ }
+ }
+ swapchain_vk->image_count = image_count;
+
+ return true;
+
+fail:
+ for (i = 0; i < image_count; ++i)
+ {
+ if (swapchain_vk->vk_semaphores[i].available)
+ VK_CALL(vkDestroySemaphore(device_vk->vk_device, swapchain_vk->vk_semaphores[i].available, NULL));
+ if (swapchain_vk->vk_semaphores[i].presentable)
+ VK_CALL(vkDestroySemaphore(device_vk->vk_device, swapchain_vk->vk_semaphores[i].presentable, NULL));
+ }
+ heap_free(swapchain_vk->vk_semaphores);
+ heap_free(swapchain_vk->vk_images);
+ return false;
+}
+
+static HRESULT wined3d_swapchain_vk_create_vulkan_swapchain(struct wined3d_swapchain_vk *swapchain_vk)
+{
+ struct wined3d_device_vk *device_vk = wined3d_device_vk(swapchain_vk->s.device);
+ const struct wined3d_swapchain_desc *desc = &swapchain_vk->s.state.desc;
+ VkSwapchainCreateInfoKHR vk_swapchain_desc;
+ VkWin32SurfaceCreateInfoKHR surface_desc;
+ unsigned int width, height, image_count;
+ const struct wined3d_vk_info *vk_info;
+ VkSurfaceCapabilitiesKHR surface_caps;
+ struct wined3d_adapter_vk *adapter_vk;
+ VkPresentModeKHR vk_present_mode;
+ VkSwapchainKHR vk_swapchain;
+ VkImageUsageFlags usage;
+ VkSurfaceKHR vk_surface;
+ VkBool32 supported;
+ VkFormat vk_format;
+ VkResult vr;
+
+ adapter_vk = wined3d_adapter_vk(device_vk->d.adapter);
+ vk_info = &adapter_vk->vk_info;
+
+ surface_desc.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
+ surface_desc.pNext = NULL;
+ surface_desc.flags = 0;
+ surface_desc.hinstance = (HINSTANCE)GetWindowLongPtrW(swapchain_vk->s.win_handle, GWLP_HINSTANCE);
+ surface_desc.hwnd = swapchain_vk->s.win_handle;
+ if ((vr = VK_CALL(vkCreateWin32SurfaceKHR(vk_info->instance, &surface_desc, NULL, &vk_surface))) < 0)
+ {
+ ERR("Failed to create Vulkan surface, vr %s.\n", wined3d_debug_vkresult(vr));
+ return E_FAIL;
+ }
+ swapchain_vk->vk_surface = vk_surface;
+
+ if ((vr = VK_CALL(vkGetPhysicalDeviceSurfaceSupportKHR(adapter_vk->physical_device,
+ device_vk->vk_queue_family_index, vk_surface, &supported))) < 0 || !supported)
+ {
+ ERR("Queue family does not support presentation on this surface, vr %s.\n", wined3d_debug_vkresult(vr));
+ goto fail;
+ }
+
+ if ((vk_format = wined3d_swapchain_vk_select_vk_format(swapchain_vk, vk_surface)) == VK_FORMAT_UNDEFINED)
+ {
+ ERR("Failed to select swapchain format.\n");
+ goto fail;
+ }
+
+ if ((vr = VK_CALL(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(adapter_vk->physical_device,
+ swapchain_vk->vk_surface, &surface_caps))) < 0)
+ {
+ ERR("Failed to get surface capabilities, vr %s.\n", wined3d_debug_vkresult(vr));
+ goto fail;
+ }
+
+ image_count = desc->backbuffer_count;
+ if (image_count < surface_caps.minImageCount)
+ image_count = surface_caps.minImageCount;
+ else if (surface_caps.maxImageCount && image_count > surface_caps.maxImageCount)
+ image_count = surface_caps.maxImageCount;
+
+ if (image_count != desc->backbuffer_count)
+ WARN("Image count %u is not supported (%u-%u).\n", desc->backbuffer_count,
+ surface_caps.minImageCount, surface_caps.maxImageCount);
+
+ width = desc->backbuffer_width;
+ if (width < surface_caps.minImageExtent.width)
+ width = surface_caps.minImageExtent.width;
+ else if (width > surface_caps.maxImageExtent.width)
+ width = surface_caps.maxImageExtent.width;
+
+ height = desc->backbuffer_height;
+ if (height < surface_caps.minImageExtent.height)
+ height = surface_caps.minImageExtent.height;
+ else if (height > surface_caps.maxImageExtent.height)
+ height = surface_caps.maxImageExtent.height;
+
+ if (width != desc->backbuffer_width || height != desc->backbuffer_height)
+ WARN("Swapchain dimensions %ux%u are not supported (%u-%u x %u-%u).\n",
+ desc->backbuffer_width, desc->backbuffer_height,
+ surface_caps.minImageExtent.width, surface_caps.maxImageExtent.width,
+ surface_caps.minImageExtent.height, surface_caps.maxImageExtent.height);
+
+ usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ usage |= surface_caps.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+ usage |= surface_caps.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+ if (!(usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) || !(usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT))
+ WARN("Transfer not supported for swapchain images.\n");
+
+ if (!(surface_caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR))
+ {
+ FIXME("Unsupported alpha mode, %#x.\n", surface_caps.supportedCompositeAlpha);
+ goto fail;
+ }
+
+ vk_present_mode = VK_PRESENT_MODE_FIFO_KHR;
+ if (!swapchain_vk->s.swap_interval)
+ {
+ if (wined3d_swapchain_vk_present_mode_supported(swapchain_vk, VK_PRESENT_MODE_IMMEDIATE_KHR))
+ vk_present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
+ else
+ FIXME("Unsupported swap interval %u.\n", swapchain_vk->s.swap_interval);
+ }
+
+ vk_swapchain_desc.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
+ vk_swapchain_desc.pNext = NULL;
+ vk_swapchain_desc.flags = 0;
+ vk_swapchain_desc.surface = vk_surface;
+ vk_swapchain_desc.minImageCount = image_count;
+ vk_swapchain_desc.imageFormat = vk_format;
+ vk_swapchain_desc.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
+ vk_swapchain_desc.imageExtent.width = width;
+ vk_swapchain_desc.imageExtent.height = height;
+ vk_swapchain_desc.imageArrayLayers = 1;
+ vk_swapchain_desc.imageUsage = usage;
+ vk_swapchain_desc.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ vk_swapchain_desc.queueFamilyIndexCount = 0;
+ vk_swapchain_desc.pQueueFamilyIndices = NULL;
+ vk_swapchain_desc.preTransform = surface_caps.currentTransform;
+ vk_swapchain_desc.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+ vk_swapchain_desc.presentMode = vk_present_mode;
+ vk_swapchain_desc.clipped = VK_TRUE;
+ vk_swapchain_desc.oldSwapchain = VK_NULL_HANDLE;
+ if ((vr = VK_CALL(vkCreateSwapchainKHR(device_vk->vk_device, &vk_swapchain_desc, NULL, &vk_swapchain))) < 0)
+ {
+ ERR("Failed to create Vulkan swapchain, vr %s.\n", wined3d_debug_vkresult(vr));
+ goto fail;
+ }
+ swapchain_vk->vk_swapchain = vk_swapchain;
+
+ if (!wined3d_swapchain_vk_create_vulkan_swapchain_images(swapchain_vk, vk_swapchain))
+ {
+ VK_CALL(vkDestroySwapchainKHR(device_vk->vk_device, vk_swapchain, NULL));
+ goto fail;
+ }
+
+ return WINED3D_OK;
+
+fail:
+ VK_CALL(vkDestroySurfaceKHR(vk_info->instance, vk_surface, NULL));
+ return E_FAIL;
+}
+
+static HRESULT wined3d_swapchain_vk_recreate(struct wined3d_swapchain_vk *swapchain_vk)
+{
+ TRACE("swapchain_vk %p.\n", swapchain_vk);
+
+ wined3d_swapchain_vk_destroy_vulkan_swapchain(swapchain_vk);
+
+ return wined3d_swapchain_vk_create_vulkan_swapchain(swapchain_vk);
+}
+
+static void wined3d_swapchain_vk_set_swap_interval(struct wined3d_swapchain_vk *swapchain_vk,
+ unsigned int swap_interval)
+{
+ if (swap_interval > 1)
+ {
+ if (swap_interval <= 4)
+ FIXME("Unsupported swap interval %u.\n", swap_interval);
+ swap_interval = 1;
+ }
+
+ if (swapchain_vk->s.swap_interval == swap_interval)
+ return;
+
+ swapchain_vk->s.swap_interval = swap_interval;
+ wined3d_swapchain_vk_recreate(swapchain_vk);
+}
+
+static void wined3d_swapchain_vk_blit(struct wined3d_swapchain_vk *swapchain_vk,
+ struct wined3d_context_vk *context_vk, const RECT *src_rect, const RECT *dst_rect, unsigned int swap_interval)
+{
+ struct wined3d_texture_vk *back_buffer_vk = wined3d_texture_vk(swapchain_vk->s.back_buffers[0]);
+ struct wined3d_device_vk *device_vk = wined3d_device_vk(swapchain_vk->s.device);
+ const struct wined3d_swapchain_desc *desc = &swapchain_vk->s.state.desc;
+ const struct wined3d_vk_info *vk_info = context_vk->vk_info;
+ VkCommandBuffer vk_command_buffer;
+ VkPresentInfoKHR present_desc;
+ unsigned int present_idx;
+ VkImageLayout vk_layout;
+ uint32_t image_idx;
+ VkImageBlit blit;
+ VkResult vr;
+ HRESULT hr;
+
+ static const VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+
+ wined3d_swapchain_vk_set_swap_interval(swapchain_vk, swap_interval);
+
+ present_idx = swapchain_vk->current++ % swapchain_vk->image_count;
+ wined3d_context_vk_wait_command_buffer(context_vk, swapchain_vk->vk_semaphores[present_idx].command_buffer_id);
+ vr = VK_CALL(vkAcquireNextImageKHR(device_vk->vk_device, swapchain_vk->vk_swapchain, UINT64_MAX,
+ swapchain_vk->vk_semaphores[present_idx].available, VK_NULL_HANDLE, &image_idx));
+ if (vr == VK_ERROR_OUT_OF_DATE_KHR)
+ {
+ if (FAILED(hr = wined3d_swapchain_vk_recreate(swapchain_vk)))
+ {
+ ERR("Failed to recreate swapchain, hr %#x.\n", hr);
+ return;
+ }
+ vr = VK_CALL(vkAcquireNextImageKHR(device_vk->vk_device, swapchain_vk->vk_swapchain, UINT64_MAX,
+ swapchain_vk->vk_semaphores[present_idx].available, VK_NULL_HANDLE, &image_idx));
+ }
+ if (vr < 0)
+ {
+ ERR("Failed to acquire next Vulkan image, vr %s.\n", wined3d_debug_vkresult(vr));
+ return;
+ }
+
+ vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk);
+
+ wined3d_context_vk_end_current_render_pass(context_vk);
+
+ wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
+ VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ vk_access_mask_from_bind_flags(back_buffer_vk->t.resource.bind_flags),
+ VK_ACCESS_TRANSFER_READ_BIT,
+ back_buffer_vk->layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ back_buffer_vk->vk_image, VK_IMAGE_ASPECT_COLOR_BIT);
+
+ wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ 0, VK_ACCESS_TRANSFER_WRITE_BIT,
+ VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ swapchain_vk->vk_images[image_idx], VK_IMAGE_ASPECT_COLOR_BIT);
+
+ blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ blit.srcSubresource.mipLevel = 0;
+ blit.srcSubresource.baseArrayLayer = 0;
+ blit.srcSubresource.layerCount = 1;
+ blit.srcOffsets[0].x = src_rect->left;
+ blit.srcOffsets[0].y = src_rect->top;
+ blit.srcOffsets[0].z = 0;
+ blit.srcOffsets[1].x = src_rect->right;
+ blit.srcOffsets[1].y = src_rect->bottom;
+ blit.srcOffsets[1].z = 1;
+ blit.dstSubresource = blit.srcSubresource;
+ blit.dstOffsets[0].x = dst_rect->left;
+ blit.dstOffsets[0].y = dst_rect->top;
+ blit.dstOffsets[0].z = 0;
+ blit.dstOffsets[1].x = dst_rect->right;
+ blit.dstOffsets[1].y = dst_rect->bottom;
+ blit.dstOffsets[1].z = 1;
+ VK_CALL(vkCmdBlitImage(vk_command_buffer,
+ back_buffer_vk->vk_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ swapchain_vk->vk_images[image_idx], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ 1, &blit, VK_FILTER_NEAREST));
+
+ wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
+ VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
+ VK_ACCESS_TRANSFER_WRITE_BIT, 0,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
+ swapchain_vk->vk_images[image_idx], VK_IMAGE_ASPECT_COLOR_BIT);
+
+ if (desc->swap_effect == WINED3D_SWAP_EFFECT_DISCARD || desc->swap_effect == WINED3D_SWAP_EFFECT_FLIP_DISCARD)
+ vk_layout = VK_IMAGE_LAYOUT_UNDEFINED;
+ else
+ vk_layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+ wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
+ VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
+ VK_ACCESS_TRANSFER_READ_BIT,
+ vk_access_mask_from_bind_flags(back_buffer_vk->t.resource.bind_flags),
+ vk_layout, back_buffer_vk->layout,
+ back_buffer_vk->vk_image, VK_IMAGE_ASPECT_COLOR_BIT);
+
+ swapchain_vk->vk_semaphores[present_idx].command_buffer_id = context_vk->current_command_buffer.id;
+ wined3d_context_vk_submit_command_buffer(context_vk,
+ 1, &swapchain_vk->vk_semaphores[present_idx].available, &wait_stage,
+ 1, &swapchain_vk->vk_semaphores[present_idx].presentable);
+
+ present_desc.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
+ present_desc.pNext = NULL;
+ present_desc.waitSemaphoreCount = 1;
+ present_desc.pWaitSemaphores = &swapchain_vk->vk_semaphores[present_idx].presentable;
+ present_desc.swapchainCount = 1;
+ present_desc.pSwapchains = &swapchain_vk->vk_swapchain;
+ present_desc.pImageIndices = &image_idx;
+ present_desc.pResults = NULL;
+ if ((vr = VK_CALL(vkQueuePresentKHR(device_vk->vk_queue, &present_desc))))
+ ERR("Present returned vr %s.\n", wined3d_debug_vkresult(vr));
+}
+
+static void wined3d_swapchain_vk_rotate(struct wined3d_swapchain *swapchain, struct wined3d_context_vk *context_vk)
+{
+ struct wined3d_texture_sub_resource *sub_resource;
+ struct wined3d_texture_vk *texture, *texture_prev;
+ struct wined3d_allocator_block *memory0;
+ VkDescriptorImageInfo vk_info0;
+ VkDeviceMemory vk_memory0;
+ VkImageLayout vk_layout0;
+ VkImage vk_image0;
+ DWORD locations0;
+ unsigned int i;
+ uint64_t id0;
+
+ static const DWORD supported_locations = WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_RB_MULTISAMPLE;
+
+ if (swapchain->state.desc.backbuffer_count < 2)
+ return;
+
+ texture_prev = wined3d_texture_vk(swapchain->back_buffers[0]);
+
+ /* Back buffer 0 is already in the draw binding. */
+ vk_image0 = texture_prev->vk_image;
+ memory0 = texture_prev->memory;
+ vk_memory0 = texture_prev->vk_memory;
+ vk_layout0 = texture_prev->layout;
+ id0 = texture_prev->command_buffer_id;
+ vk_info0 = texture_prev->default_image_info;
+ locations0 = texture_prev->t.sub_resources[0].locations;
+
+ for (i = 1; i < swapchain->state.desc.backbuffer_count; ++i)
+ {
+ texture = wined3d_texture_vk(swapchain->back_buffers[i]);
+ sub_resource = &texture->t.sub_resources[0];
+
+ if (!(sub_resource->locations & supported_locations))
+ wined3d_texture_load_location(&texture->t, 0, &context_vk->c, texture->t.resource.draw_binding);
+
+ texture_prev->vk_image = texture->vk_image;
+ texture_prev->memory = texture->memory;
+ texture_prev->vk_memory = texture->vk_memory;
+ texture_prev->layout = texture->layout;
+ texture_prev->command_buffer_id = texture->command_buffer_id;
+ texture_prev->default_image_info = texture->default_image_info;
+
+ wined3d_texture_validate_location(&texture_prev->t, 0, sub_resource->locations & supported_locations);
+ wined3d_texture_invalidate_location(&texture_prev->t, 0, ~(sub_resource->locations & supported_locations));
+
+ texture_prev = texture;
+ }
+
+ texture_prev->vk_image = vk_image0;
+ texture_prev->memory = memory0;
+ texture_prev->vk_memory = vk_memory0;
+ texture_prev->layout = vk_layout0;
+ texture_prev->command_buffer_id = id0;
+ texture_prev->default_image_info = vk_info0;
+
+ wined3d_texture_validate_location(&texture_prev->t, 0, locations0 & supported_locations);
+ wined3d_texture_invalidate_location(&texture_prev->t, 0, ~(locations0 & supported_locations));
+
+ device_invalidate_state(swapchain->device, STATE_FRAMEBUFFER);
+}
+
static void swapchain_vk_present(struct wined3d_swapchain *swapchain, const RECT *src_rect,
const RECT *dst_rect, unsigned int swap_interval, uint32_t flags)
{
- FIXME("Not implemented.\n");
+ struct wined3d_swapchain_vk *swapchain_vk = wined3d_swapchain_vk(swapchain);
+ struct wined3d_texture *back_buffer = swapchain->back_buffers[0];
+ struct wined3d_context_vk *context_vk;
+
+ context_vk = wined3d_context_vk(context_acquire(swapchain->device, back_buffer, 0));
+
+ wined3d_texture_load_location(back_buffer, 0, &context_vk->c, back_buffer->resource.draw_binding);
+
+ if (swapchain_vk->vk_swapchain)
+ wined3d_swapchain_vk_blit(swapchain_vk, context_vk, src_rect, dst_rect, swap_interval);
+
+ wined3d_swapchain_vk_rotate(swapchain, context_vk);
+
+ wined3d_texture_validate_location(swapchain->front_buffer, 0, WINED3D_LOCATION_DRAWABLE);
+ wined3d_texture_invalidate_location(swapchain->front_buffer, 0, ~WINED3D_LOCATION_DRAWABLE);
+
+ TRACE("Starting new frame.\n");
+
+ context_release(&context_vk->c);
}
static const struct wined3d_swapchain_ops swapchain_vk_ops =
@@ -994,13 +1584,30 @@ HRESULT wined3d_swapchain_gl_init(struct wined3d_swapchain_gl *swapchain_gl, str
return hr;
}
-HRESULT wined3d_swapchain_vk_init(struct wined3d_swapchain *swapchain_vk, struct wined3d_device *device,
+HRESULT wined3d_swapchain_vk_init(struct wined3d_swapchain_vk *swapchain_vk, struct wined3d_device *device,
struct wined3d_swapchain_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops)
{
+ HRESULT hr;
+
TRACE("swapchain_vk %p, device %p, desc %p, parent %p, parent_ops %p.\n",
swapchain_vk, device, desc, parent, parent_ops);
- return wined3d_swapchain_init(swapchain_vk, device, desc, parent, parent_ops, &swapchain_vk_ops);
+ if (FAILED(hr = wined3d_swapchain_init(&swapchain_vk->s, device, desc, parent, parent_ops, &swapchain_vk_ops)))
+ return hr;
+
+ if (swapchain_vk->s.win_handle == GetDesktopWindow())
+ {
+ WARN("Creating a desktop window swapchain.\n");
+ return hr;
+ }
+
+ if (FAILED(hr = wined3d_swapchain_vk_create_vulkan_swapchain(swapchain_vk)))
+ {
+ wined3d_swapchain_cleanup(&swapchain_vk->s);
+ return hr;
+ }
+
+ return hr;
}
HRESULT CDECL wined3d_swapchain_create(struct wined3d_device *device, struct wined3d_swapchain_desc *desc,
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 8eee18ad17a..d96f27ccc69 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -5084,7 +5084,29 @@ HRESULT wined3d_swapchain_gl_init(struct wined3d_swapchain_gl *swapchain_gl,
struct wined3d_device *device, struct wined3d_swapchain_desc *desc,
void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
-HRESULT wined3d_swapchain_vk_init(struct wined3d_swapchain *swapchain_vk,
+struct wined3d_swapchain_vk
+{
+ struct wined3d_swapchain s;
+
+ VkSwapchainKHR vk_swapchain;
+ VkSurfaceKHR vk_surface;
+ VkImage *vk_images;
+ struct
+ {
+ VkSemaphore available;
+ VkSemaphore presentable;
+ uint64_t command_buffer_id;
+ } *vk_semaphores;
+ unsigned int current, image_count;
+};
+
+static inline struct wined3d_swapchain_vk *wined3d_swapchain_vk(struct wined3d_swapchain *swapchain)
+{
+ return CONTAINING_RECORD(swapchain, struct wined3d_swapchain_vk, s);
+}
+
+void wined3d_swapchain_vk_cleanup(struct wined3d_swapchain_vk *swapchain_vk) DECLSPEC_HIDDEN;
+HRESULT wined3d_swapchain_vk_init(struct wined3d_swapchain_vk *swapchain_vk,
struct wined3d_device *device, struct wined3d_swapchain_desc *desc,
void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
diff --git a/dlls/wined3d/wined3d_vk.h b/dlls/wined3d/wined3d_vk.h
index 4a872bcdaa0..ae81fe945ee 100644
--- a/dlls/wined3d/wined3d_vk.h
+++ b/dlls/wined3d/wined3d_vk.h
@@ -41,7 +41,15 @@
VK_INSTANCE_PFN(vkGetPhysicalDeviceSparseImageFormatProperties) \
/* Vulkan 1.1 */ \
VK_INSTANCE_EXT_PFN(vkGetPhysicalDeviceFeatures2) \
- VK_INSTANCE_EXT_PFN(vkGetPhysicalDeviceProperties2)
+ VK_INSTANCE_EXT_PFN(vkGetPhysicalDeviceProperties2) \
+ /* VK_KHR_surface */ \
+ VK_INSTANCE_PFN(vkDestroySurfaceKHR) \
+ VK_INSTANCE_PFN(vkGetPhysicalDeviceSurfaceCapabilitiesKHR) \
+ VK_INSTANCE_PFN(vkGetPhysicalDeviceSurfaceFormatsKHR) \
+ VK_INSTANCE_PFN(vkGetPhysicalDeviceSurfacePresentModesKHR) \
+ VK_INSTANCE_PFN(vkGetPhysicalDeviceSurfaceSupportKHR) \
+ /* VK_KHR_win32_surface */ \
+ VK_INSTANCE_PFN(vkCreateWin32SurfaceKHR)
#define VK_DEVICE_FUNCS() \
VK_DEVICE_PFN(vkAllocateCommandBuffers) \
@@ -163,7 +171,13 @@
VK_DEVICE_PFN(vkSetEvent) \
VK_DEVICE_PFN(vkUnmapMemory) \
VK_DEVICE_PFN(vkUpdateDescriptorSets) \
- VK_DEVICE_PFN(vkWaitForFences)
+ VK_DEVICE_PFN(vkWaitForFences) \
+ /* VK_KHR_swapchain */ \
+ VK_DEVICE_PFN(vkAcquireNextImageKHR) \
+ VK_DEVICE_PFN(vkCreateSwapchainKHR) \
+ VK_DEVICE_PFN(vkDestroySwapchainKHR) \
+ VK_DEVICE_PFN(vkGetSwapchainImagesKHR) \
+ VK_DEVICE_PFN(vkQueuePresentKHR)
#define DECLARE_VK_PFN(name) PFN_##name name;
--
2.20.1
May 29, 2020
[PATCH 4/5] wined3d: Move swapchain buffer discarding to wined3d_cs_exec_present().
by Henri Verbeet
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/wined3d/cs.c | 20 ++++++++++++++++++--
dlls/wined3d/swapchain.c | 22 ----------------------
2 files changed, 18 insertions(+), 24 deletions(-)
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index ffd00c9b950..b87003c53b8 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -522,11 +522,14 @@ static void wined3d_cs_exec_nop(struct wined3d_cs *cs, const void *data)
static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data)
{
struct wined3d_texture *logo_texture, *cursor_texture, *back_buffer;
+ struct wined3d_rendertarget_view *dsv = cs->state.fb.depth_stencil;
const struct wined3d_cs_present *op = data;
+ const struct wined3d_swapchain_desc *desc;
struct wined3d_swapchain *swapchain;
unsigned int i;
swapchain = op->swapchain;
+ desc = &swapchain->state.desc;
back_buffer = swapchain->back_buffers[0];
wined3d_swapchain_set_window(swapchain, op->dst_window_override);
@@ -557,7 +560,7 @@ static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data)
TRACE("Rendering the software cursor.\n");
- if (swapchain->state.desc.windowed)
+ if (desc->windowed)
MapWindowPoints(NULL, swapchain->win_handle, (POINT *)&dst_rect, 2);
if (wined3d_clip_blit(&clip_rect, &dst_rect, &src_rect))
wined3d_texture_blt(back_buffer, 0, &dst_rect, cursor_texture, 0,
@@ -566,6 +569,19 @@ static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data)
swapchain->swapchain_ops->swapchain_present(swapchain, &op->src_rect, &op->dst_rect, op->swap_interval, op->flags);
+ /* Discard buffers if the swap effect allows it. */
+ back_buffer = swapchain->back_buffers[desc->backbuffer_count - 1];
+ if (desc->swap_effect == WINED3D_SWAP_EFFECT_DISCARD || desc->swap_effect == WINED3D_SWAP_EFFECT_FLIP_DISCARD)
+ wined3d_texture_validate_location(back_buffer, 0, WINED3D_LOCATION_DISCARDED);
+
+ if (dsv && dsv->resource->type != WINED3D_RTYPE_BUFFER)
+ {
+ struct wined3d_texture *ds = texture_from_resource(dsv->resource);
+
+ if ((desc->flags & WINED3D_SWAPCHAIN_DISCARD_DEPTHSTENCIL || ds->flags & WINED3D_TEXTURE_DISCARD))
+ wined3d_rendertarget_view_validate_location(dsv, WINED3D_LOCATION_DISCARDED);
+ }
+
if (TRACE_ON(fps))
{
DWORD time = GetTickCount();
@@ -582,7 +598,7 @@ static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data)
}
wined3d_resource_release(&swapchain->front_buffer->resource);
- for (i = 0; i < swapchain->state.desc.backbuffer_count; ++i)
+ for (i = 0; i < desc->backbuffer_count; ++i)
{
wined3d_resource_release(&swapchain->back_buffers[i]->resource);
}
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index 289013f4e99..465ab08eb82 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -467,8 +467,6 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain,
struct wined3d_swapchain_gl *swapchain_gl = wined3d_swapchain_gl(swapchain);
const struct wined3d_swapchain_desc *desc = &swapchain->state.desc;
struct wined3d_texture *back_buffer = swapchain->back_buffers[0];
- const struct wined3d_fb_state *fb = &swapchain->device->cs->state.fb;
- struct wined3d_rendertarget_view *dsv = fb->depth_stencil;
const struct wined3d_gl_info *gl_info;
struct wined3d_context_gl *context_gl;
struct wined3d_context *context;
@@ -532,26 +530,6 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain,
wined3d_texture_validate_location(swapchain->front_buffer, 0, WINED3D_LOCATION_DRAWABLE);
wined3d_texture_invalidate_location(swapchain->front_buffer, 0, ~WINED3D_LOCATION_DRAWABLE);
- /* If the swapeffect is DISCARD, the back buffer is undefined. That means the SYSMEM
- * and INTEXTURE copies can keep their old content if they have any defined content.
- * If the swapeffect is COPY, the content remains the same.
- *
- * The FLIP swap effect is not implemented yet. We could mark WINED3D_LOCATION_DRAWABLE
- * up to date and hope WGL flipped front and back buffers and read this data into
- * the FBO. Don't bother about this for now. */
- if (desc->swap_effect == WINED3D_SWAP_EFFECT_DISCARD
- || desc->swap_effect == WINED3D_SWAP_EFFECT_FLIP_DISCARD)
- wined3d_texture_validate_location(swapchain->back_buffers[desc->backbuffer_count - 1],
- 0, WINED3D_LOCATION_DISCARDED);
-
- if (dsv && dsv->resource->type != WINED3D_RTYPE_BUFFER)
- {
- struct wined3d_texture *ds = texture_from_resource(dsv->resource);
-
- if ((desc->flags & WINED3D_SWAPCHAIN_DISCARD_DEPTHSTENCIL
- || ds->flags & WINED3D_TEXTURE_DISCARD))
- wined3d_texture_validate_location(ds, dsv->sub_resource_idx, WINED3D_LOCATION_DISCARDED);
- }
context_release(context);
}
--
2.20.1
May 29, 2020
[PATCH 3/5] wined3d: Map Vulkan adapter bo's persistently on 64-bit architectures.
by Henri Verbeet
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/wined3d/adapter_vk.c | 9 +++++++++
dlls/wined3d/context_vk.c | 5 +++++
dlls/wined3d/wined3d_private.h | 1 +
3 files changed, 15 insertions(+)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c
index 0cd77c4e6b3..cbde5d3683c 100644
--- a/dlls/wined3d/adapter_vk.c
+++ b/dlls/wined3d/adapter_vk.c
@@ -844,6 +844,9 @@ static void *wined3d_bo_vk_map(struct wined3d_bo_vk *bo, struct wined3d_context_
void *map_ptr;
VkResult vr;
+ if (bo->map_ptr)
+ return bo->map_ptr;
+
vk_info = context_vk->vk_info;
device_vk = wined3d_device_vk(context_vk->c.device);
@@ -872,6 +875,9 @@ static void *wined3d_bo_vk_map(struct wined3d_bo_vk *bo, struct wined3d_context_
return NULL;
}
+ if (sizeof(map_ptr) >= sizeof(uint64_t))
+ bo->map_ptr = map_ptr;
+
return map_ptr;
}
@@ -881,6 +887,9 @@ static void wined3d_bo_vk_unmap(struct wined3d_bo_vk *bo, struct wined3d_context
struct wined3d_device_vk *device_vk;
struct wined3d_bo_slab_vk *slab;
+ if (bo->map_ptr)
+ return;
+
if ((slab = bo->slab))
{
if (--slab->map_count)
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c
index 45924eb16b1..a7c77dd5a6b 100644
--- a/dlls/wined3d/context_vk.c
+++ b/dlls/wined3d/context_vk.c
@@ -483,6 +483,7 @@ BOOL wined3d_context_vk_create_bo(struct wined3d_context_vk *context_vk, VkDevic
return FALSE;
}
+ bo->map_ptr = NULL;
bo->buffer_offset = 0;
bo->size = size;
bo->usage = usage;
@@ -791,6 +792,8 @@ void wined3d_context_vk_destroy_sampler(struct wined3d_context_vk *context_vk,
void wined3d_context_vk_destroy_bo(struct wined3d_context_vk *context_vk, const struct wined3d_bo_vk *bo)
{
+ struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
+ const struct wined3d_vk_info *vk_info = context_vk->vk_info;
size_t object_size, idx;
TRACE("context_vk %p, bo %p.\n", context_vk, bo);
@@ -810,6 +813,8 @@ void wined3d_context_vk_destroy_bo(struct wined3d_context_vk *context_vk, const
return;
}
+ if (bo->map_ptr)
+ VK_CALL(vkUnmapMemory(device_vk->vk_device, bo->vk_memory));
wined3d_context_vk_destroy_memory(context_vk, bo->vk_memory, bo->command_buffer_id);
}
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 49379b3ca5d..8eee18ad17a 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1554,6 +1554,7 @@ struct wined3d_bo_vk
struct wined3d_bo_slab_vk *slab;
VkDeviceMemory vk_memory;
+ void *map_ptr;
VkDeviceSize buffer_offset;
VkDeviceSize memory_offset;
--
2.20.1
May 29, 2020
[PATCH 2/5] wined3d: Initialise more caps and limits in wined3d_adapter_vk_init_d3d_info().
by Henri Verbeet
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/wined3d/adapter_vk.c | 71 ++++++++++++++++++++++++++++++++++++---
1 file changed, 67 insertions(+), 4 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c
index f8929ddf1fd..0cd77c4e6b3 100644
--- a/dlls/wined3d/adapter_vk.c
+++ b/dlls/wined3d/adapter_vk.c
@@ -2068,13 +2068,76 @@ static void adapter_vk_init_driver_info(struct wined3d_adapter_vk *adapter_vk,
wined3d_driver_info_init(&adapter_vk->a.driver_info, gpu_description, vram_bytes, sysmem_bytes);
}
-static void wined3d_adapter_vk_init_d3d_info(struct wined3d_adapter *adapter, uint32_t wined3d_creation_flags)
+static enum wined3d_feature_level feature_level_from_caps(const struct shader_caps *shader_caps)
{
- struct wined3d_d3d_info *d3d_info = &adapter->d3d_info;
+ unsigned int shader_model;
+
+ shader_model = min(shader_caps->vs_version, shader_caps->ps_version);
+ shader_model = min(shader_model, max(shader_caps->gs_version, 3));
+ shader_model = min(shader_model, max(shader_caps->hs_version, 4));
+ shader_model = min(shader_model, max(shader_caps->ds_version, 4));
+
+ if (shader_model >= 5)
+ return WINED3D_FEATURE_LEVEL_11_1;
+
+ if (shader_model >= 4)
+ return WINED3D_FEATURE_LEVEL_10_1;
+
+ return WINED3D_FEATURE_LEVEL_NONE;
+}
+
+static void wined3d_adapter_vk_init_d3d_info(struct wined3d_adapter_vk *adapter_vk, uint32_t wined3d_creation_flags)
+{
+ struct wined3d_d3d_info *d3d_info = &adapter_vk->a.d3d_info;
+ struct wined3d_vertex_caps vertex_caps;
+ struct fragment_caps fragment_caps;
+ struct shader_caps shader_caps;
+
+ adapter_vk->a.shader_backend->shader_get_caps(&adapter_vk->a, &shader_caps);
+ adapter_vk->a.vertex_pipe->vp_get_caps(&adapter_vk->a, &vertex_caps);
+ adapter_vk->a.fragment_pipe->get_caps(&adapter_vk->a, &fragment_caps);
+
+ d3d_info->limits.vs_version = shader_caps.vs_version;
+ d3d_info->limits.hs_version = shader_caps.hs_version;
+ d3d_info->limits.ds_version = shader_caps.ds_version;
+ d3d_info->limits.gs_version = shader_caps.gs_version;
+ d3d_info->limits.ps_version = shader_caps.ps_version;
+ d3d_info->limits.cs_version = shader_caps.cs_version;
+ d3d_info->limits.vs_uniform_count = shader_caps.vs_uniform_count;
+ d3d_info->limits.ps_uniform_count = shader_caps.ps_uniform_count;
+ d3d_info->limits.varying_count = shader_caps.varying_count;
+ d3d_info->limits.ffp_textures = fragment_caps.MaxSimultaneousTextures;
+ d3d_info->limits.ffp_blend_stages = fragment_caps.MaxTextureBlendStages;
+ d3d_info->limits.ffp_vertex_blend_matrices = vertex_caps.max_vertex_blend_matrices;
+ d3d_info->limits.active_light_count = vertex_caps.max_active_lights;
+
+ d3d_info->limits.max_rt_count = WINED3D_MAX_RENDER_TARGETS;
+ d3d_info->limits.max_clip_distances = WINED3D_MAX_CLIP_DISTANCES;
+ d3d_info->limits.texture_size = adapter_vk->device_limits.maxImageDimension2D;
+ d3d_info->limits.pointsize_max = adapter_vk->device_limits.pointSizeRange[1];
d3d_info->wined3d_creation_flags = wined3d_creation_flags;
- d3d_info->texture_swizzle = TRUE;
+ d3d_info->xyzrhw = vertex_caps.xyzrhw;
+ d3d_info->emulated_flatshading = vertex_caps.emulated_flatshading;
+ d3d_info->ffp_generic_attributes = vertex_caps.ffp_generic_attributes;
+ d3d_info->ffp_alpha_test = false;
+ d3d_info->vs_clipping = !!(shader_caps.wined3d_caps & WINED3D_SHADER_CAP_VS_CLIPPING);
+ d3d_info->shader_color_key = !!(fragment_caps.wined3d_caps & WINED3D_FRAGMENT_CAP_COLOR_KEY);
+ d3d_info->shader_double_precision = !!(shader_caps.wined3d_caps & WINED3D_SHADER_CAP_DOUBLE_PRECISION);
+ d3d_info->shader_output_interpolation = !!(shader_caps.wined3d_caps & WINED3D_SHADER_CAP_OUTPUT_INTERPOLATION);
+ d3d_info->viewport_array_index_any_shader = false; /* VK_EXT_shader_viewport_index_layer */
+ d3d_info->texture_npot = true;
+ d3d_info->texture_npot_conditional = true;
+ d3d_info->draw_base_vertex_offset = true;
+ d3d_info->vertex_bgra = true;
+ d3d_info->texture_swizzle = true;
+ d3d_info->srgb_read_control = false;
+ d3d_info->srgb_write_control = false;
+ d3d_info->clip_control = true;
+ d3d_info->full_ffp_varyings = !!(shader_caps.wined3d_caps & WINED3D_SHADER_CAP_FULL_FFP_VARYINGS);
+ d3d_info->scaled_resolve = false;
+ d3d_info->feature_level = feature_level_from_caps(&shader_caps);
d3d_info->multisample_draw_location = WINED3D_LOCATION_TEXTURE_RGB;
}
@@ -2130,7 +2193,7 @@ static BOOL wined3d_adapter_vk_init(struct wined3d_adapter_vk *adapter_vk,
adapter->misc_state_template = misc_state_template_vk;
adapter->shader_backend = wined3d_spirv_shader_backend_init_vk();
- wined3d_adapter_vk_init_d3d_info(adapter, wined3d_creation_flags);
+ wined3d_adapter_vk_init_d3d_info(adapter_vk, wined3d_creation_flags);
return TRUE;
--
2.20.1
May 29, 2020
[PATCH 1/5] wined3d: Use wined3d_buffer_vk_get_buffer_info() when binding Vulkan vertex buffers.
by Henri Verbeet
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/wined3d/context_vk.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c
index 5cb04310d67..45924eb16b1 100644
--- a/dlls/wined3d/context_vk.c
+++ b/dlls/wined3d/context_vk.c
@@ -2194,9 +2194,10 @@ static void wined3d_context_vk_bind_vertex_buffers(struct wined3d_context_vk *co
VkDeviceSize offsets[ARRAY_SIZE(state->streams)] = {0};
VkBuffer buffers[ARRAY_SIZE(state->streams)];
const struct wined3d_stream_state *stream;
+ const VkDescriptorBufferInfo *buffer_info;
+ struct wined3d_buffer_vk *buffer_vk;
struct wined3d_buffer *buffer;
unsigned int i, first, count;
- struct wined3d_bo_vk *bo;
first = 0;
count = 0;
@@ -2206,10 +2207,11 @@ static void wined3d_context_vk_bind_vertex_buffers(struct wined3d_context_vk *co
if ((buffer = stream->buffer))
{
- bo = &wined3d_buffer_vk(buffer)->bo;
- wined3d_context_vk_reference_bo(context_vk, bo);
- buffers[count] = bo->vk_buffer;
- offsets[count] = bo->buffer_offset + stream->offset;
+ buffer_vk = wined3d_buffer_vk(buffer);
+ buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
+ wined3d_context_vk_reference_bo(context_vk, &buffer_vk->bo);
+ buffers[count] = buffer_info->buffer;
+ offsets[count] = buffer_info->offset + stream->offset;
++count;
continue;
}
--
2.20.1
May 29, 2020
[PATCH 7/7] dwrite: Implement chaining contextual substitution of format 2.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/opentype.c | 128 ++++++++++++++++++++++++++++-------------
1 file changed, 87 insertions(+), 41 deletions(-)
diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c
index 5114e900df6..f4e9d3305a4 100644
--- a/dlls/dwrite/opentype.c
+++ b/dlls/dwrite/opentype.c
@@ -3536,6 +3536,13 @@ static BOOL opentype_match_glyph_func(UINT16 glyph, UINT16 glyph_data, const str
return glyph == glyph_data;
}
+static BOOL opentype_match_class_func(UINT16 glyph, UINT16 glyph_data, const struct match_data *data)
+{
+ const struct match_context *mc = data->mc;
+ UINT16 glyph_class = opentype_layout_get_glyph_class(&mc->context->table->table, data->subtable_offset, glyph);
+ return glyph_class == glyph_data;
+}
+
static BOOL opentype_match_coverage_func(UINT16 glyph, UINT16 glyph_data, const struct match_data *data)
{
const struct match_context *mc = data->mc;
@@ -5145,14 +5152,57 @@ static BOOL opentype_layout_apply_gsub_chain_context_lookup(unsigned int backtra
opentype_layout_context_gsub_apply_lookup(mc->context, input_count, match_positions, lookup_count, lookup_records, match_length);
}
+static BOOL opentype_layout_apply_chain_rule_set(const struct match_context *mc, unsigned int offset)
+{
+ unsigned int backtrack_count, input_count, lookahead_count, lookup_count;
+ const struct dwrite_fonttable *table = &mc->context->table->table;
+ const UINT16 *backtrack, *lookahead, *input, *lookup_records;
+ const struct ot_gsub_ruleset *ruleset;
+ unsigned int i, count;
+
+ count = table_read_be_word(table, offset);
+ ruleset = table_read_ensure(table, offset, count * sizeof(ruleset->offsets));
+
+ for (i = 0; i < count; ++i)
+ {
+ unsigned int rule_offset = offset + GET_BE_WORD(ruleset->offsets[i]);
+
+ backtrack_count = table_read_be_word(table, rule_offset);
+ rule_offset += 2;
+ backtrack = table_read_ensure(table, rule_offset, backtrack_count * sizeof(*backtrack));
+ rule_offset += backtrack_count * sizeof(*backtrack);
+
+ input_count = table_read_be_word(table, rule_offset);
+ rule_offset += 2;
+ input = table_read_ensure(table, rule_offset, input_count * sizeof(*input));
+ rule_offset += input_count * sizeof(*input);
+
+ lookahead_count = table_read_be_word(table, rule_offset);
+ rule_offset += 2;
+ lookahead = table_read_ensure(table, rule_offset, lookahead_count * sizeof(*lookahead));
+ rule_offset += lookahead_count * sizeof(*lookahead);
+
+ lookup_count = table_read_be_word(table, rule_offset);
+ rule_offset += 2;
+ lookup_records = table_read_ensure(table, rule_offset, lookup_count * 2 * sizeof(*lookup_records));
+
+ /* First applicable rule is used. */
+ if (opentype_layout_apply_gsub_chain_context_lookup(backtrack_count, backtrack, input_count, input, lookahead_count,
+ lookahead, lookup_count, lookup_records, mc))
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scriptshaping_context *context,
const struct lookup *lookup, unsigned int subtable_offset)
{
struct match_context mc = { .context = context, .mask = lookup->mask };
const struct dwrite_fonttable *table = &context->table->table;
- unsigned int i, coverage_index = GLYPH_NOT_COVERED, count, offset;
- unsigned int backtrack_count, input_count, lookahead_count, lookup_count;
- const UINT16 *backtrack, *lookahead, *input, *lookup_records;
+ unsigned int coverage_index = GLYPH_NOT_COVERED, count, offset;
UINT16 glyph, format, coverage;
BOOL ret = FALSE;
@@ -5162,8 +5212,6 @@ static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scripts
if (format == 1)
{
- const struct ot_gsub_ruleset *ruleset;
-
coverage = table_read_be_word(table, subtable_offset +
FIELD_OFFSET(struct ot_gsub_chaincontext_subst_format1, coverage));
@@ -5180,51 +5228,48 @@ static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scripts
rulesets[coverage_index]));
offset += subtable_offset;
- count = table_read_be_word(table, offset);
- ruleset = table_read_ensure(table, offset, count * sizeof(ruleset->offsets));
-
mc.match_func = opentype_match_glyph_func;
- for (i = 0; i < count; ++i)
- {
- unsigned int rule_offset = offset + GET_BE_WORD(ruleset->offsets[i]);
-
- backtrack_count = table_read_be_word(table, rule_offset);
- rule_offset += 2;
- backtrack = table_read_ensure(table, rule_offset, backtrack_count * sizeof(*backtrack));
- rule_offset += backtrack_count * sizeof(*backtrack);
-
- input_count = table_read_be_word(table, rule_offset);
- rule_offset += 2;
- input = table_read_ensure(table, rule_offset, input_count * sizeof(*input));
- rule_offset += input_count * sizeof(*input);
-
- lookahead_count = table_read_be_word(table, rule_offset);
- rule_offset += 2;
- lookahead = table_read_ensure(table, rule_offset, lookahead_count * sizeof(*lookahead));
- rule_offset += lookahead_count * sizeof(*lookahead);
-
- lookup_count = table_read_be_word(table, rule_offset);
- rule_offset += 2;
- lookup_records = table_read_ensure(table, rule_offset, lookup_count * 2 * sizeof(*lookup_records));
-
- /* First applicable rule is used. */
- if (opentype_layout_apply_gsub_chain_context_lookup(backtrack_count, backtrack, input_count, input, lookahead_count,
- lookahead, lookup_count, lookup_records, &mc))
- {
- return TRUE;
- }
- }
+
+ ret = opentype_layout_apply_chain_rule_set(&mc, offset);
}
else if (format == 2)
{
- coverage = table_read_be_word(table, subtable_offset +
- FIELD_OFFSET(struct ot_gsub_chaincontext_subst_format1, coverage));
+ unsigned int backtrack_classdef, input_classdef, lookahead_classdef, rule_set_idx;
+
+ offset = subtable_offset + 2 /* format */;
+
+ coverage = table_read_be_word(table, offset);
+ offset += 2;
coverage_index = opentype_layout_is_glyph_covered(table, subtable_offset + coverage, glyph);
if (coverage_index == GLYPH_NOT_COVERED)
return FALSE;
- WARN("Chaining contextual substitution (2) is not supported.\n");
+ backtrack_classdef = table_read_be_word(table, offset) + subtable_offset;
+ offset += 2;
+
+ input_classdef = table_read_be_word(table, offset) + subtable_offset;
+ offset += 2;
+
+ lookahead_classdef = table_read_be_word(table, offset) + subtable_offset;
+ offset += 2;
+
+ count = table_read_be_word(table, offset);
+ offset+= 2;
+
+ rule_set_idx = opentype_layout_get_glyph_class(table, input_classdef, glyph);
+ if (rule_set_idx >= count)
+ return FALSE;
+
+ offset = table_read_be_word(table, offset + rule_set_idx * 2);
+ offset += subtable_offset;
+
+ mc.backtrack_offset = backtrack_classdef;
+ mc.input_offset = input_classdef;
+ mc.lookahead_offset = lookahead_classdef;
+ mc.match_func = opentype_match_class_func;
+
+ ret = opentype_layout_apply_chain_rule_set(&mc, offset);
}
else if (format == 3)
{
@@ -5262,6 +5307,7 @@ static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scripts
mc.input_offset = subtable_offset;
mc.lookahead_offset = subtable_offset;
mc.match_func = opentype_match_coverage_func;
+
ret = opentype_layout_apply_gsub_chain_context_lookup(backtrack_count, backtrack, input_count, input + 1,
lookahead_count, lookahead, lookup_count, lookup_records, &mc);
}
--
2.26.2
May 29, 2020
[PATCH 6/7] dwrite: Implement chaining contextual substitution of format 1.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/opentype.c | 63 ++++++++++++++++++++++++++++++++++++++++--
1 file changed, 60 insertions(+), 3 deletions(-)
diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c
index 198da43f2cd..5114e900df6 100644
--- a/dlls/dwrite/opentype.c
+++ b/dlls/dwrite/opentype.c
@@ -618,6 +618,12 @@ struct ot_gsub_chaincontext_subst_format1
UINT16 rulesets[1];
};
+struct ot_gsub_ruleset
+{
+ UINT16 count;
+ UINT16 offsets[1];
+};
+
struct ot_feature
{
WORD feature_params;
@@ -3525,6 +3531,11 @@ struct ot_gdef_mark_glyph_sets
DWORD offsets[1];
};
+static BOOL opentype_match_glyph_func(UINT16 glyph, UINT16 glyph_data, const struct match_data *data)
+{
+ return glyph == glyph_data;
+}
+
static BOOL opentype_match_coverage_func(UINT16 glyph, UINT16 glyph_data, const struct match_data *data)
{
const struct match_context *mc = data->mc;
@@ -5139,7 +5150,9 @@ static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scripts
{
struct match_context mc = { .context = context, .mask = lookup->mask };
const struct dwrite_fonttable *table = &context->table->table;
- unsigned int coverage_index = GLYPH_NOT_COVERED;
+ unsigned int i, coverage_index = GLYPH_NOT_COVERED, count, offset;
+ unsigned int backtrack_count, input_count, lookahead_count, lookup_count;
+ const UINT16 *backtrack, *lookahead, *input, *lookup_records;
UINT16 glyph, format, coverage;
BOOL ret = FALSE;
@@ -5149,6 +5162,8 @@ static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scripts
if (format == 1)
{
+ const struct ot_gsub_ruleset *ruleset;
+
coverage = table_read_be_word(table, subtable_offset +
FIELD_OFFSET(struct ot_gsub_chaincontext_subst_format1, coverage));
@@ -5156,7 +5171,49 @@ static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scripts
if (coverage_index == GLYPH_NOT_COVERED)
return FALSE;
- WARN("Chaining contextual substitution (1) is not supported.\n");
+ count = table_read_be_word(table, subtable_offset + FIELD_OFFSET(struct ot_gsub_chaincontext_subst_format1,
+ ruleset_count));
+ if (coverage_index >= count)
+ return FALSE;
+
+ offset = table_read_be_word(table, subtable_offset + FIELD_OFFSET(struct ot_gsub_chaincontext_subst_format1,
+ rulesets[coverage_index]));
+ offset += subtable_offset;
+
+ count = table_read_be_word(table, offset);
+ ruleset = table_read_ensure(table, offset, count * sizeof(ruleset->offsets));
+
+ mc.match_func = opentype_match_glyph_func;
+ for (i = 0; i < count; ++i)
+ {
+ unsigned int rule_offset = offset + GET_BE_WORD(ruleset->offsets[i]);
+
+ backtrack_count = table_read_be_word(table, rule_offset);
+ rule_offset += 2;
+ backtrack = table_read_ensure(table, rule_offset, backtrack_count * sizeof(*backtrack));
+ rule_offset += backtrack_count * sizeof(*backtrack);
+
+ input_count = table_read_be_word(table, rule_offset);
+ rule_offset += 2;
+ input = table_read_ensure(table, rule_offset, input_count * sizeof(*input));
+ rule_offset += input_count * sizeof(*input);
+
+ lookahead_count = table_read_be_word(table, rule_offset);
+ rule_offset += 2;
+ lookahead = table_read_ensure(table, rule_offset, lookahead_count * sizeof(*lookahead));
+ rule_offset += lookahead_count * sizeof(*lookahead);
+
+ lookup_count = table_read_be_word(table, rule_offset);
+ rule_offset += 2;
+ lookup_records = table_read_ensure(table, rule_offset, lookup_count * 2 * sizeof(*lookup_records));
+
+ /* First applicable rule is used. */
+ if (opentype_layout_apply_gsub_chain_context_lookup(backtrack_count, backtrack, input_count, input, lookahead_count,
+ lookahead, lookup_count, lookup_records, &mc))
+ {
+ return TRUE;
+ }
+ }
}
else if (format == 2)
{
@@ -5174,7 +5231,7 @@ static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scripts
unsigned int backtrack_count, input_count, lookahead_count, lookup_count;
const UINT16 *backtrack, *lookahead, *input, *lookup_records;
- unsigned int offset = subtable_offset + 2 /* format */;
+ offset = subtable_offset + 2 /* format */;
backtrack_count = table_read_be_word(table, offset);
offset += 2;
--
2.26.2
May 29, 2020
[PATCH 5/7] dwrite: Use iterator matching for chain substitution.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/opentype.c | 105 ++++++++++++++++++++++++++---------------
1 file changed, 67 insertions(+), 38 deletions(-)
diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c
index 468368bcc03..198da43f2cd 100644
--- a/dlls/dwrite/opentype.c
+++ b/dlls/dwrite/opentype.c
@@ -3474,7 +3474,24 @@ enum iterator_match
ITER_MAYBE,
};
-typedef BOOL (*p_match_func)(UINT16 glyph, UINT16 glyph_data, const void *match_data);
+struct match_context;
+struct match_data
+{
+ const struct match_context *mc;
+ unsigned int subtable_offset;
+};
+
+typedef BOOL (*p_match_func)(UINT16 glyph, UINT16 glyph_data, const struct match_data *match_data);
+
+struct match_context
+{
+ struct scriptshaping_context *context;
+ unsigned int backtrack_offset;
+ unsigned int input_offset;
+ unsigned int lookahead_offset;
+ p_match_func match_func;
+ unsigned int mask;
+};
struct glyph_iterator
{
@@ -3485,7 +3502,7 @@ struct glyph_iterator
unsigned int mask;
p_match_func match_func;
const UINT16 *glyph_data;
- const void *match_data;
+ const struct match_data *match_data;
};
static void glyph_iterator_init(struct scriptshaping_context *context, unsigned int flags, unsigned int pos,
@@ -3495,7 +3512,7 @@ static void glyph_iterator_init(struct scriptshaping_context *context, unsigned
iter->flags = flags;
iter->pos = pos;
iter->len = len;
- iter->mask = ~0u; /* TODO: input sequences should be using actual mask */
+ iter->mask = ~0u;
iter->match_func = NULL;
iter->match_data = NULL;
iter->glyph_data = NULL;
@@ -3508,6 +3525,13 @@ struct ot_gdef_mark_glyph_sets
DWORD offsets[1];
};
+static BOOL opentype_match_coverage_func(UINT16 glyph, UINT16 glyph_data, const struct match_data *data)
+{
+ const struct match_context *mc = data->mc;
+ return opentype_layout_is_glyph_covered(&mc->context->table->table, data->subtable_offset + GET_BE_WORD(glyph_data), glyph)
+ != GLYPH_NOT_COVERED;
+}
+
static BOOL opentype_layout_mark_set_covers(const struct scriptshaping_cache *cache, unsigned int set_index,
UINT16 glyph)
{
@@ -4947,32 +4971,32 @@ static BOOL opentype_layout_apply_gsub_lig_substitution(struct scriptshaping_con
return FALSE;
}
-#define CHAIN_CONTEXT_MAX_LENGTH 64
+#define GLYPH_CONTEXT_MAX_LENGTH 64
-static BOOL opentype_layout_context_match_input(struct scriptshaping_context *context, unsigned int subtable_offset,
- unsigned int count, const UINT16 *input, unsigned int *end_offset, unsigned int *match_positions)
+static BOOL opentype_layout_context_match_input(const struct match_context *mc, unsigned int count, const UINT16 *input,
+ unsigned int *end_offset, unsigned int *match_positions)
{
+ struct match_data match_data = { .mc = mc, .subtable_offset = mc->input_offset };
+ struct scriptshaping_context *context = mc->context;
struct glyph_iterator iter;
unsigned int i;
- UINT16 glyph;
- if (count > CHAIN_CONTEXT_MAX_LENGTH)
+ if (count > GLYPH_CONTEXT_MAX_LENGTH)
return FALSE;
match_positions[0] = context->cur;
glyph_iterator_init(context, 0, context->cur, count - 1, &iter);
+ iter.mask = mc->mask;
+ iter.match_func = mc->match_func;
+ iter.match_data = &match_data;
+ iter.glyph_data = input;
for (i = 1; i < count; ++i)
{
if (!glyph_iterator_next(&iter))
return FALSE;
- /* TODO: this only covers Format3 substitution */
- glyph = context->u.subst.glyphs[iter.pos];
- if (opentype_layout_is_glyph_covered(&context->table->table, subtable_offset + GET_BE_WORD(input[i]), glyph) == GLYPH_NOT_COVERED)
- return FALSE;
-
match_positions[i] = iter.pos;
}
@@ -4981,23 +5005,23 @@ static BOOL opentype_layout_context_match_input(struct scriptshaping_context *co
return TRUE;
}
-static BOOL opentype_layout_context_match_backtrack(struct scriptshaping_context *context, unsigned int subtable_offset,
- unsigned int count, const UINT16 *backtrack, unsigned int *match_start)
+static BOOL opentype_layout_context_match_backtrack(const struct match_context *mc, unsigned int count,
+ const UINT16 *backtrack, unsigned int *match_start)
{
+ struct match_data match_data = { .mc = mc, .subtable_offset = mc->backtrack_offset };
+ struct scriptshaping_context *context = mc->context;
struct glyph_iterator iter;
unsigned int i;
- UINT16 glyph;
glyph_iterator_init(context, 0, context->cur, count, &iter);
+ iter.match_func = mc->match_func;
+ iter.match_data = &match_data;
+ iter.glyph_data = backtrack;
for (i = 0; i < count; ++i)
{
if (!glyph_iterator_prev(&iter))
return FALSE;
-
- glyph = context->u.subst.glyphs[iter.pos];
- if (opentype_layout_is_glyph_covered(&context->table->table, subtable_offset + GET_BE_WORD(backtrack[i]), glyph) == GLYPH_NOT_COVERED)
- return FALSE;
}
*match_start = iter.pos;
@@ -5005,23 +5029,23 @@ static BOOL opentype_layout_context_match_backtrack(struct scriptshaping_context
return TRUE;
}
-static BOOL opentype_layout_context_match_lookahead(struct scriptshaping_context *context, unsigned int subtable_offset,
- unsigned int count, const UINT16 *lookahead, unsigned int offset, unsigned int *end_index)
+static BOOL opentype_layout_context_match_lookahead(const struct match_context *mc, unsigned int count,
+ const UINT16 *lookahead, unsigned int offset, unsigned int *end_index)
{
+ struct match_data match_data = { .mc = mc, .subtable_offset = mc->lookahead_offset };
+ struct scriptshaping_context *context = mc->context;
struct glyph_iterator iter;
unsigned int i;
- UINT16 glyph;
glyph_iterator_init(context, 0, context->cur + offset - 1, count, &iter);
+ iter.match_func = mc->match_func;
+ iter.match_data = &match_data;
+ iter.glyph_data = lookahead;
for (i = 0; i < count; ++i)
{
if (!glyph_iterator_next(&iter))
return FALSE;
-
- glyph = context->u.subst.glyphs[iter.pos];
- if (opentype_layout_is_glyph_covered(&context->table->table, subtable_offset + GET_BE_WORD(lookahead[i]), glyph) == GLYPH_NOT_COVERED)
- return FALSE;
}
*end_index = iter.pos;
@@ -5071,7 +5095,7 @@ static BOOL opentype_layout_context_gsub_apply_lookup(struct scriptshaping_conte
if (delta > 0)
{
- if (delta + count > CHAIN_CONTEXT_MAX_LENGTH)
+ if (delta + count > GLYPH_CONTEXT_MAX_LENGTH)
break;
}
else
@@ -5097,22 +5121,23 @@ static BOOL opentype_layout_context_gsub_apply_lookup(struct scriptshaping_conte
return TRUE;
}
-static BOOL opentype_layout_apply_gsub_chain_context_lookup(struct scriptshaping_context *context, unsigned int subtable_offset,
- unsigned int backtrack_count, const UINT16 *backtrack, unsigned int input_count, const UINT16 *input,
- unsigned int lookahead_count, const UINT16 *lookahead, unsigned int lookup_count, const UINT16 *lookup_records)
+static BOOL opentype_layout_apply_gsub_chain_context_lookup(unsigned int backtrack_count, const UINT16 *backtrack,
+ unsigned int input_count, const UINT16 *input, unsigned int lookahead_count, const UINT16 *lookahead,
+ unsigned int lookup_count, const UINT16 *lookup_records, const struct match_context *mc)
{
unsigned int start_index = 0, match_length = 0, end_index = 0;
- unsigned int match_positions[CHAIN_CONTEXT_MAX_LENGTH];
+ unsigned int match_positions[GLYPH_CONTEXT_MAX_LENGTH];
- return opentype_layout_context_match_input(context, subtable_offset, input_count, input, &match_length, match_positions) &&
- opentype_layout_context_match_backtrack(context, subtable_offset, backtrack_count, backtrack, &start_index) &&
- opentype_layout_context_match_lookahead(context, subtable_offset, lookahead_count, lookahead, input_count, &end_index) &&
- opentype_layout_context_gsub_apply_lookup(context, input_count, match_positions, lookup_count, lookup_records, match_length);
+ return opentype_layout_context_match_input(mc, input_count, input, &match_length, match_positions) &&
+ opentype_layout_context_match_backtrack(mc, backtrack_count, backtrack, &start_index) &&
+ opentype_layout_context_match_lookahead(mc, lookahead_count, lookahead, input_count, &end_index) &&
+ opentype_layout_context_gsub_apply_lookup(mc->context, input_count, match_positions, lookup_count, lookup_records, match_length);
}
static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scriptshaping_context *context,
const struct lookup *lookup, unsigned int subtable_offset)
{
+ struct match_context mc = { .context = context, .mask = lookup->mask };
const struct dwrite_fonttable *table = &context->table->table;
unsigned int coverage_index = GLYPH_NOT_COVERED;
UINT16 glyph, format, coverage;
@@ -5176,8 +5201,12 @@ static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scripts
if (coverage_index == GLYPH_NOT_COVERED)
return FALSE;
- ret = opentype_layout_apply_gsub_chain_context_lookup(context, subtable_offset, backtrack_count, backtrack,
- input_count, input + 1, lookahead_count, lookahead, lookup_count, lookup_records);
+ mc.backtrack_offset = subtable_offset;
+ mc.input_offset = subtable_offset;
+ mc.lookahead_offset = subtable_offset;
+ mc.match_func = opentype_match_coverage_func;
+ ret = opentype_layout_apply_gsub_chain_context_lookup(backtrack_count, backtrack, input_count, input + 1,
+ lookahead_count, lookahead, lookup_count, lookup_records, &mc);
}
else
WARN("Unknown chaining contextual substitution format %u.\n", format);
--
2.26.2
May 29, 2020