blob: 0a5586118c3ebad2174ea57a0959847e14a37486 [file] [log] [blame]
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/ganesh/vk/GrVkSamplerYcbcrConversion.h"
#include "src/gpu/ganesh/vk/GrVkGpu.h"
GrVkSamplerYcbcrConversion* GrVkSamplerYcbcrConversion::Create(
GrVkGpu* gpu, const GrVkYcbcrConversionInfo& info) {
if (!gpu->vkCaps().supportsYcbcrConversion()) {
return nullptr;
}
#ifdef SK_DEBUG
const VkFormatFeatureFlags& featureFlags = info.fFormatFeatures;
if (info.fXChromaOffset == VK_CHROMA_LOCATION_MIDPOINT ||
info.fYChromaOffset == VK_CHROMA_LOCATION_MIDPOINT) {
SkASSERT(featureFlags & VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT);
}
if (info.fXChromaOffset == VK_CHROMA_LOCATION_COSITED_EVEN ||
info.fYChromaOffset == VK_CHROMA_LOCATION_COSITED_EVEN) {
SkASSERT(featureFlags & VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT);
}
if (info.fChromaFilter == VK_FILTER_LINEAR) {
SkASSERT(featureFlags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT);
}
if (info.fForceExplicitReconstruction) {
SkASSERT(featureFlags &
VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT);
}
#endif
VkSamplerYcbcrConversionCreateInfo ycbcrCreateInfo;
ycbcrCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO;
ycbcrCreateInfo.pNext = nullptr;
ycbcrCreateInfo.format = info.fFormat;
ycbcrCreateInfo.ycbcrModel = info.fYcbcrModel;
ycbcrCreateInfo.ycbcrRange = info.fYcbcrRange;
// Components is ignored for external format conversions. For all other formats identity swizzle
// is used. It can be added to GrVkYcbcrConversionInfo if necessary.
ycbcrCreateInfo.components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY};
ycbcrCreateInfo.xChromaOffset = info.fXChromaOffset;
ycbcrCreateInfo.yChromaOffset = info.fYChromaOffset;
ycbcrCreateInfo.chromaFilter = info.fChromaFilter;
ycbcrCreateInfo.forceExplicitReconstruction = info.fForceExplicitReconstruction;
#ifdef SK_BUILD_FOR_ANDROID
VkExternalFormatANDROID externalFormat;
if (info.fExternalFormat) {
// Format must not be specified for external images.
SkASSERT(info.fFormat == VK_FORMAT_UNDEFINED);
externalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID;
externalFormat.pNext = nullptr;
externalFormat.externalFormat = info.fExternalFormat;
ycbcrCreateInfo.pNext = &externalFormat;
}
#else
// External images are supported only on Android;
SkASSERT(!info.fExternalFormat);
#endif
if (!info.fExternalFormat) {
SkASSERT(info.fFormat != VK_FORMAT_UNDEFINED);
}
VkSamplerYcbcrConversion conversion;
VkResult result;
GR_VK_CALL_RESULT(gpu, result, CreateSamplerYcbcrConversion(gpu->device(), &ycbcrCreateInfo,
nullptr, &conversion));
if (result != VK_SUCCESS) {
return nullptr;
}
return new GrVkSamplerYcbcrConversion(gpu, conversion, GenerateKey(info));
}
void GrVkSamplerYcbcrConversion::freeGPUData() const {
SkASSERT(fYcbcrConversion);
GR_VK_CALL(fGpu->vkInterface(), DestroySamplerYcbcrConversion(fGpu->device(),
fYcbcrConversion, nullptr));
}
GrVkSamplerYcbcrConversion::Key GrVkSamplerYcbcrConversion::GenerateKey(
const GrVkYcbcrConversionInfo& ycbcrInfo) {
SkASSERT(static_cast<int>(ycbcrInfo.fYcbcrModel <= 7));
static const int kRangeShift = 3;
SkASSERT(static_cast<int>(ycbcrInfo.fYcbcrRange) <= 1);
static const int kXChromaOffsetShift = kRangeShift + 1;
SkASSERT(static_cast<int>(ycbcrInfo.fXChromaOffset) <= 1);
static const int kYChromaOffsetShift = kXChromaOffsetShift + 1;
SkASSERT(static_cast<int>(ycbcrInfo.fXChromaOffset) <= 1);
static const int kChromaFilterShift = kYChromaOffsetShift + 1;
SkASSERT(static_cast<int>(ycbcrInfo.fChromaFilter) <= 1);
static const int kReconShift = kChromaFilterShift + 1;
SkASSERT(static_cast<int>(ycbcrInfo.fForceExplicitReconstruction) <= 1);
static_assert(kReconShift <= 7);
uint8_t ycbcrKey = static_cast<uint8_t>(ycbcrInfo.fYcbcrModel);
ycbcrKey |= (static_cast<uint8_t>(ycbcrInfo.fYcbcrRange) << kRangeShift);
ycbcrKey |= (static_cast<uint8_t>(ycbcrInfo.fXChromaOffset) << kXChromaOffsetShift);
ycbcrKey |= (static_cast<uint8_t>(ycbcrInfo.fYChromaOffset) << kYChromaOffsetShift);
ycbcrKey |= (static_cast<uint8_t>(ycbcrInfo.fChromaFilter) << kChromaFilterShift);
ycbcrKey |= (static_cast<uint8_t>(ycbcrInfo.fForceExplicitReconstruction) << kReconShift);
return Key{ycbcrInfo.fFormat, ycbcrInfo.fExternalFormat, ycbcrKey};
}