This adds support for the modifiers portion of the WSI "extension".
Reviewed-by: Daniel Stone <daniels@collabora.com>
*/
#include "anv_private.h"
+#include "drm_fourcc.h"
#include "vk_enum_to_str.h"
#include "vk_format_info.h"
#include "vk_util.h"
return flags;
}
+static void
+get_wsi_format_modifier_properties_list(const struct anv_physical_device *physical_device,
+ VkFormat vk_format,
+ struct wsi_format_modifier_properties_list *list)
+{
+ const struct anv_format *anv_format = anv_get_format(vk_format);
+
+ VK_OUTARRAY_MAKE(out, list->modifier_properties, &list->modifier_count);
+
+ /* This is a simplified list where all the modifiers are available */
+ assert(vk_format == VK_FORMAT_B8G8R8_SRGB ||
+ vk_format == VK_FORMAT_B8G8R8_UNORM ||
+ vk_format == VK_FORMAT_B8G8R8A8_SRGB ||
+ vk_format == VK_FORMAT_B8G8R8A8_UNORM);
+
+ uint64_t modifiers[] = {
+ DRM_FORMAT_MOD_LINEAR,
+ I915_FORMAT_MOD_X_TILED,
+ I915_FORMAT_MOD_Y_TILED,
+ };
+
+ for (uint32_t i = 0; i < ARRAY_SIZE(modifiers); i++) {
+ vk_outarray_append(&out, mod_props) {
+ mod_props->modifier = modifiers[i];
+ if (isl_drm_modifier_has_aux(modifiers[i]))
+ mod_props->modifier_plane_count = 2;
+ else
+ mod_props->modifier_plane_count = anv_format->n_planes;
+ }
+ }
+}
+
void anv_GetPhysicalDeviceFormatProperties(
VkPhysicalDevice physicalDevice,
VkFormat vk_format,
VkFormat format,
VkFormatProperties2KHR* pFormatProperties)
{
+ ANV_FROM_HANDLE(anv_physical_device, physical_device, physicalDevice);
anv_GetPhysicalDeviceFormatProperties(physicalDevice, format,
&pFormatProperties->formatProperties);
vk_foreach_struct(ext, pFormatProperties->pNext) {
switch (ext->sType) {
+ case VK_STRUCTURE_TYPE_WSI_FORMAT_MODIFIER_PROPERTIES_LIST_MESA:
+ get_wsi_format_modifier_properties_list(physical_device, format,
+ (void *)ext);
+ break;
default:
anv_debug_ignored_stype(ext->sType);
break;
return VK_SUCCESS;
}
+static uint32_t
+score_drm_format_mod(uint64_t modifier)
+{
+ switch (modifier) {
+ case DRM_FORMAT_MOD_LINEAR: return 1;
+ case I915_FORMAT_MOD_X_TILED: return 2;
+ case I915_FORMAT_MOD_Y_TILED: return 3;
+ default: unreachable("bad DRM format modifier");
+ }
+}
+
+static const struct isl_drm_modifier_info *
+choose_drm_format_mod(const struct anv_physical_device *device,
+ uint32_t modifier_count, const uint64_t *modifiers)
+{
+ uint64_t best_mod = UINT64_MAX;
+ uint32_t best_score = 0;
+
+ for (uint32_t i = 0; i < modifier_count; ++i) {
+ uint32_t score = score_drm_format_mod(modifiers[i]);
+ if (score > best_score) {
+ best_mod = modifiers[i];
+ best_score = score;
+ }
+ }
+
+ if (best_score > 0)
+ return isl_drm_modifier_get_info(best_mod);
+ else
+ return NULL;
+}
+
VkResult
anv_image_create(VkDevice _device,
const struct anv_image_create_info *create_info,
const struct wsi_image_create_info *wsi_info =
vk_find_struct_const(pCreateInfo->pNext, WSI_IMAGE_CREATE_INFO_MESA);
+ if (wsi_info && wsi_info->modifier_count > 0) {
+ isl_mod_info = choose_drm_format_mod(&device->instance->physicalDevice,
+ wsi_info->modifier_count,
+ wsi_info->modifiers);
+ assert(isl_mod_info);
+ }
anv_assert(pCreateInfo->mipLevels > 0);
anv_assert(pCreateInfo->arrayLayers > 0);
image->tiling = pCreateInfo->tiling;
image->disjoint = pCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT_KHR;
image->needs_set_tiling = wsi_info && wsi_info->scanout;
+ image->drm_format_mod = isl_mod_info ? isl_mod_info->modifier :
+ DRM_FORMAT_MOD_INVALID;
const struct anv_format *format = anv_get_format(image->vk_format);
assert(format != NULL);
*/
bool needs_set_tiling;
+ /**
+ * Must be DRM_FORMAT_MOD_INVALID unless tiling is
+ * VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT.
+ */
+ uint64_t drm_format_mod;
+
VkDeviceSize size;
uint32_t alignment;
return anv_lookup_entrypoint(&physical_device->info, pName);
}
+static uint64_t
+anv_wsi_image_get_modifier(VkImage _image)
+{
+ ANV_FROM_HANDLE(anv_image, image, _image);
+ return image->drm_format_mod;
+}
+
VkResult
anv_init_wsi(struct anv_physical_device *physical_device)
{
- return wsi_device_init(&physical_device->wsi_device,
- anv_physical_device_to_handle(physical_device),
- anv_wsi_proc_addr,
- &physical_device->instance->alloc);
+ VkResult result;
+
+ result = wsi_device_init(&physical_device->wsi_device,
+ anv_physical_device_to_handle(physical_device),
+ anv_wsi_proc_addr,
+ &physical_device->instance->alloc);
+ if (result != VK_SUCCESS)
+ return result;
+
+ physical_device->wsi_device.supports_modifiers = true;
+ physical_device->wsi_device.image_get_modifier = anv_wsi_image_get_modifier;
+
+ return VK_SUCCESS;
}
void