| /* | |
| * Copyright 2026 Google LLC | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "tests/Test.h" | |
| #if defined(SK_GRAPHITE) && defined(SK_VULKAN) && defined(SK_BUILD_FOR_ANDROID) | |
| #include "include/gpu/graphite/precompile/PrecompileRuntimeEffect.h" | |
| #include "include/gpu/graphite/precompile/PrecompileShader.h" | |
| #include "include/gpu/graphite/vk/precompile/VulkanPrecompileShader.h" | |
| #include "include/gpu/vk/VulkanTypes.h" | |
| #include "tests/graphite/precompile/AndroidRuntimeEffectManager.h" | |
| #include "tests/graphite/precompile/PrecompileTestUtils.h" | |
| using namespace skgpu::graphite; | |
| using namespace PrecompileTestUtils; | |
| namespace { | |
| // Used in lieu of SkEnumBitMask to avoid adding casts when copying in precompile cases. | |
| static constexpr DrawTypeFlags operator|(DrawTypeFlags a, DrawTypeFlags b) { | |
| return static_cast<DrawTypeFlags>(static_cast<std::underlying_type<DrawTypeFlags>::type>(a) | | |
| static_cast<std::underlying_type<DrawTypeFlags>::type>(b)); | |
| } | |
| constexpr DrawTypeFlags kRRectAndNonAARect = | |
| static_cast<DrawTypeFlags>(DrawTypeFlags::kAnalyticRRect | | |
| DrawTypeFlags::kNonAAFillRect); | |
| static const SkColorInfo kRGBA8Premul(kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr); | |
| static const skgpu::graphite::RenderPassProperties kRGBA_1_D_SRGB { | |
| skgpu::graphite::DepthStencilFlags::kDepth, | |
| kRGBA_8888_SkColorType, | |
| SkColorSpace::MakeSRGB(), | |
| /* fRequiresMSAA= */ false | |
| }; | |
| static const skgpu::graphite::RenderPassProperties kRGBA_4_DS_SRGB { | |
| skgpu::graphite::DepthStencilFlags::kDepthStencil, | |
| kRGBA_8888_SkColorType, | |
| SkColorSpace::MakeSRGB(), | |
| /* fRequiresMSAA= */ true | |
| }; | |
| static const skgpu::graphite::RenderPassProperties kRGBA16F_1_D_SRGB { | |
| skgpu::graphite::DepthStencilFlags::kDepth, | |
| kRGBA_F16_SkColorType, | |
| SkColorSpace::MakeSRGB(), | |
| /* fRequiresMSAA= */ false | |
| }; | |
| static const SkColorInfo kRGBA8PremulHLG(kRGBA_8888_SkColorType, | |
| kPremul_SkAlphaType, | |
| SkColorSpace::MakeRGB(SkNamedTransferFn::kHLG, | |
| SkNamedGamut::kRec2020)); | |
| static const SkColorInfo kRGBA8PremulPQ(kRGBA_8888_SkColorType, | |
| kPremul_SkAlphaType, | |
| SkColorSpace::MakeRGB(SkNamedTransferFn::kPQ, | |
| SkNamedGamut::kRec2020)); | |
| static const SkColorInfo kRGBA8Premul2020(kRGBA_8888_SkColorType, | |
| kPremul_SkAlphaType, | |
| SkColorSpace::MakeRGB(SkNamedTransferFn::kRec2020_12bit, | |
| SkNamedGamut::kRec2020)); | |
| static PipelineLabel kPixel8Cases[] = { | |
| { -1, "RP((RGBA8+D16 x1).rgba) + CoverBoundsRenderStep[NonAAFill] + LocalMatrix[CoordNormalize[HardwareImage(x238 709+narrow mid mid linear F rgba cf1lf1)]+PreAlpha] SrcOver" }, | |
| { -1, "RP((RGBA8+D16 x1).rgba) + AnalyticRRectRenderStep + LocalMatrix[CoordNormalize[HardwareImage(x238 709+narrow mid mid linear F rgba cf1lf1)]+PreAlpha] SrcOver" }, | |
| { -1, "RP((RGBA8+D16 x1).rgba) + AnalyticRRectRenderStep + LocalMatrix[CoordNormalize[HardwareImage(x238 601+narrow mid mid linear F rgba cf1lf1)]+PreAlpha] SrcOver" }, | |
| { -1, "RP((RGBA8+D16 x1).rgba) + CoverBoundsRenderStep[NonAAFill] + LocalMatrix[CoordNormalize[HardwareImage(x238 601+narrow mid mid linear F rgba cf1lf1)]+PreAlpha] SrcOver" }, | |
| { -1, "RP((RGBA8+D16 x1).rgba) + AnalyticRRectRenderStep + BlendCompose[LocalMatrix[CoordNormalize[HardwareImage(x238 601+narrow mid mid linear F rgba cf1lf1)]+PreAlpha], AlphaOnlyPaintColor, SrcIn] SrcOver" }, | |
| { -1, "RP((RGBA8+D16 x1).rgba) + AnalyticRRectRenderStep + BlendCompose[LocalMatrix[CoordNormalize[HardwareImage(x238 709+narrow mid mid linear F rgba cf1lf1)]+PreAlpha], AlphaOnlyPaintColor, SrcIn] SrcOver" }, | |
| { -1, "RP((RGBA8+D16 x1).rgba) + CoverBoundsRenderStep[NonAAFill] + LocalMatrix[CoordNormalize[HardwareImage(x238 709+narrow mid mid linear F rgba cf1lf1)]+PreAlpha] SrcOver AnalyticClip" }, | |
| { -1, "RP((RGBA8+D16 x1).rgba) + CoverBoundsRenderStep[NonAAFill] + Compose[RE_LinearEffect_UNKNOWN__SRGB__false__UNKNOWN__Shader[RE_MouriMap_TonemapEffect[LocalMatrix[CoordNormalize[HardwareImage(x247 2020+narrow cos cos linear F rgba cf1lf1)]+Unpremul+HLG+Gamut+Premul], LocalMatrix[CoordNormalize[HardwareImage(0)]+Passthrough]]+Unpremul+sRGB+Premul]+Unpremul+sRGB+Premul, Dither] SrcOver" }, | |
| { -1, "RP((RGBA8+D16 x1).rgba) + AnalyticRRectRenderStep + Compose[RE_LinearEffect_BT2020_HLG__UNKNOWN__false__UNKNOWN__Shader[LocalMatrix[CoordNormalize[HardwareImage(x247 2020+narrow cos cos linear F rgba cf1lf1)]+Unpremul+HLG+Gamut+sRGB+Premul]]+Unpremul+sRGB+Premul, Dither] SrcOver" }, | |
| { -1, "RP((RGBA8+D16 x1).rgba) + CoverBoundsRenderStep[NonAAFill] + Compose[RE_LinearEffect_BT2020_HLG__UNKNOWN__false__UNKNOWN__Shader[LocalMatrix[CoordNormalize[HardwareImage(x247 2020+narrow cos cos linear F rgba cf1lf1)]+Unpremul+HLG+Gamut+sRGB+Premul]]+Unpremul+sRGB+Premul, Dither] SrcOver" }, | |
| { -1, "RP((RGBA16F+D16 x1).rgba) + CoverBoundsRenderStep[NonAAFill] + RE_MouriMap_CrossTalkAndChunk16x16Effect[LocalMatrix[CoordNormalize[HardwareImage(x247 2020+narrow cos cos linear F rgba cf1lf1)]+Unpremul+HLG+Gamut+sRGB+Premul]] Src" }, | |
| { -1, "RP((RGBA16F+D16 x1).rgba) + CoverBoundsRenderStep[NonAAFill] + RE_LinearEffect_UNKNOWN__SRGB__false__UNKNOWN__Shader[RE_MouriMap_TonemapEffect[LocalMatrix[CoordNormalize[HardwareImage(x247 2020+narrow cos cos linear F rgba cf1lf1)]+Unpremul+HLG+Gamut+Premul], LocalMatrix[CoordNormalize[HardwareImage(0)]+Passthrough]]+Unpremul+sRGB+Premul]+Unpremul+sRGB+Premul SrcOver" }, | |
| { -1, "RP((RGBA8+D16 x1).rgba) + CoverBoundsRenderStep[NonAAFill] + LocalMatrix[CoordNormalize[HardwareImage(x238 709+full mid mid linear F rgba cf1lf1)]+PreAlpha] SrcOver" }, | |
| { -1, "RP((RGBA8+D16 x1).rgba) + CoverBoundsRenderStep[NonAAFill] + BlendCompose[RE_EdgeExtensionEffect[LocalMatrix[CoordNormalize[HardwareImage(x238 709+full mid mid linear F rgba cf1lf1)]+Passthrough]], AlphaOnlyPaintColor, SrcIn] SrcOver" }, | |
| { -1, "RP((RGBA8+D16 x1).rgba) + CoverBoundsRenderStep[NonAAFill] + RE_EdgeExtensionEffect[LocalMatrix[CoordNormalize[HardwareImage(x238 709+full mid mid linear F rgba cf1lf1)]+Passthrough]] Src" }, | |
| { -1, "RP((RGBA8+D16 x1).rgba) + CoverBoundsRenderStep[NonAAFill] + Compose[RE_LinearEffect_UNKNOWN__SRGB__false__UNKNOWN__Shader[RE_MouriMap_TonemapEffect[LocalMatrix[CoordNormalize[HardwareImage(x247 2020+narrow cos cos linear F rgba cf1lf1)]+Unpremul+HLG+Gamut+Premul], LocalMatrix[CoordNormalize[HardwareImage(0)]+Passthrough]]+Unpremul+sRGB+Premul]+Unpremul+sRGB+Premul, Dither] SrcOver" }, | |
| { -1, "RP((RGBA8+D24_S8 x4->1).rgba) + CoverBoundsRenderStep[NonAAFill] + BlendCompose[RE_LinearEffect_BT2020_HLG__UNKNOWN__false__UNKNOWN__Shader[LocalMatrix[CoordNormalize[HardwareImage(x247 2020+narrow cos cos linear F rgba cf1lf1)]+Unpremul+HLG+Gamut+sRGB+Premul]]+Unpremul+sRGB+Premul, AlphaOnlyPaintColor, SrcIn]+Dither SrcOver" }, | |
| }; | |
| sk_sp<PrecompileShader> vulkan_ycbcr_image_shader(const skgpu::VulkanYcbcrConversionInfo& ycbcrInfo, | |
| const SkColorInfo& ci) { | |
| return PrecompileShaders::VulkanYCbCrImage(ycbcrInfo, | |
| PrecompileShaders::ImageShaderFlags::kExcludeCubic, | |
| { &ci, 1 }, | |
| {}); | |
| } | |
| sk_sp<PrecompileShader> wrap_in_linear_effect(RuntimeEffectManager& effectManager, | |
| const shaders::LinearEffect& linearEffect, | |
| sk_sp<PrecompileShader> child, | |
| sk_sp<SkColorSpace> outCS) { | |
| sk_sp<SkRuntimeEffect> runtimeEffect = | |
| effectManager.getOrCreateLinearRuntimeEffect(linearEffect); | |
| sk_sp<PrecompileShader> linearEffectShader = PrecompileRuntimeEffects::MakePrecompileShader( | |
| std::move(runtimeEffect), | |
| {{ {{ std::move(child) }} }}); | |
| if (outCS) { | |
| linearEffectShader = linearEffectShader->makeWithWorkingColorSpace(nullptr, outCS); | |
| } | |
| return linearEffectShader; | |
| } | |
| sk_sp<PrecompileShader> wrap_in_MouriMapToneMap(RuntimeEffectManager& effectManager, | |
| sk_sp<PrecompileShader> img) { | |
| SkColorInfo luxCI { kRGBA_F16_SkColorType, | |
| kPremul_SkAlphaType, | |
| SkColorSpace::MakeSRGBLinear() }; | |
| sk_sp<PrecompileShader> lux = PrecompileShaders::Image( | |
| PrecompileShaders::ImageShaderFlags::kExcludeCubic, | |
| { &luxCI, 1 }, | |
| {}); | |
| sk_sp<PrecompileShader> toneMap = PrecompileRuntimeEffects::MakePrecompileShader( | |
| effectManager.getKnownRuntimeEffect( | |
| RuntimeEffectManager::KnownId::kMouriMap_TonemapEffect), | |
| {{ {{ std::move(img) }}, {{ std::move(lux) }} }}); | |
| sk_sp<PrecompileShader> inLinear = | |
| toneMap->makeWithWorkingColorSpace(luxCI.refColorSpace(), nullptr); | |
| return inLinear; | |
| } | |
| sk_sp<PrecompileShader> wrap_in_MouriMapCrossTalk(RuntimeEffectManager& effectManager, | |
| sk_sp<PrecompileShader> child) { | |
| return PrecompileRuntimeEffects::MakePrecompileShader( | |
| effectManager.getKnownRuntimeEffect( | |
| RuntimeEffectManager::KnownId::kMouriMap_CrossTalkAndChunk16x16Effect), | |
| {{ {{ std::move(child) }} }}); | |
| } | |
| sk_sp<PrecompileShader> wrap_in_edge_extension(RuntimeEffectManager& effectManager, | |
| sk_sp<PrecompileShader> child) { | |
| return PrecompileRuntimeEffects::MakePrecompileShader( | |
| effectManager.getKnownRuntimeEffect(RuntimeEffectManager::KnownId::kEdgeExtensionEffect), | |
| {{ {{ std::move(child) }} }}); | |
| } | |
| // Basic external format YCbCr wrapped in a RE_LinearEffect | |
| void linear_effect_hdr(RuntimeEffectManager& effectManager, | |
| sk_sp<PrecompileShader> hdrImg, | |
| const shaders::LinearEffect& linearEffect, | |
| std::vector<PrecompileSettings>& result) { | |
| sk_sp<PrecompileShader> linear = wrap_in_linear_effect( | |
| effectManager, | |
| linearEffect, | |
| hdrImg, | |
| SkColorSpace::MakeSRGBLinear()); | |
| PaintOptions paintOptions; | |
| paintOptions.setShaders({{ std::move(linear) }}); | |
| paintOptions.setDither(true); | |
| result.push_back({ paintOptions, | |
| kRRectAndNonAARect, | |
| kRGBA_1_D_SRGB }); | |
| // This is the only MSAA Pipeline | |
| paintOptions.setPaintColorIsOpaque(false); | |
| result.push_back({ paintOptions, | |
| DrawTypeFlags::kNonAAFillRect, | |
| kRGBA_4_DS_SRGB }); | |
| } | |
| // RE_EdgeExtensionEffect wrapped in a RE_LinearEffect | |
| void linear_effect_edge_extension_hdr(RuntimeEffectManager& effectManager, | |
| sk_sp<PrecompileShader> hdrImg, | |
| const shaders::LinearEffect& linearEffect, | |
| std::vector<PrecompileSettings>& result) { | |
| sk_sp<PrecompileShader> edgeEffect = wrap_in_edge_extension(effectManager, hdrImg); | |
| sk_sp<PrecompileShader> linear = wrap_in_linear_effect( | |
| effectManager, | |
| linearEffect, | |
| std::move(edgeEffect), | |
| SkColorSpace::MakeSRGBLinear()); | |
| PaintOptions paintOptions; | |
| paintOptions.setShaders( {{ std::move(linear) }}); | |
| paintOptions.setDither(true); | |
| result.push_back({ paintOptions, | |
| DrawTypeFlags::kNonAAFillRect, | |
| kRGBA_1_D_SRGB }); | |
| } | |
| // RE_MouriMap_TonemapEffect wrapped in a RE_LinearEffect | |
| void linear_effect_mourimap_tonemap_hdr(RuntimeEffectManager& effectManager, | |
| sk_sp<PrecompileShader> hdrImg, | |
| std::vector<PrecompileSettings>& result) { | |
| static const shaders::LinearEffect kUnkSRGBfalseUnk { | |
| ui::Dataspace::UNKNOWN, | |
| ui::Dataspace::SRGB, | |
| false, | |
| ui::Dataspace::UNKNOWN, | |
| shaders::LinearEffect::Shader }; | |
| sk_sp<PrecompileShader> wrapped = wrap_in_MouriMapToneMap(effectManager, hdrImg); | |
| sk_sp<PrecompileShader> linear = wrap_in_linear_effect( | |
| effectManager, | |
| kUnkSRGBfalseUnk, | |
| std::move(wrapped), | |
| SkColorSpace::MakeSRGBLinear()); | |
| PaintOptions paintOptions; | |
| paintOptions.setShaders( {{ std::move(linear) }}); | |
| result.push_back({ paintOptions, | |
| DrawTypeFlags::kNonAAFillRect, | |
| kRGBA16F_1_D_SRGB }); | |
| paintOptions.setDither(true); | |
| result.push_back({ paintOptions, | |
| DrawTypeFlags::kNonAAFillRect, | |
| kRGBA_1_D_SRGB }); | |
| } | |
| // RE_MouriMap_CrossTalkAndChunk16x16Effect [ ... ] | |
| void mourimap_crosstalk_and_chunk_hdr(RuntimeEffectManager& effectManager, | |
| sk_sp<PrecompileShader> hdrImg, | |
| std::vector<PrecompileSettings>& result) { | |
| sk_sp<PrecompileShader> wrapped = wrap_in_MouriMapCrossTalk(effectManager, hdrImg); | |
| PaintOptions paintOptions; | |
| paintOptions.setShaders( {{ std::move(wrapped) }}); | |
| paintOptions.setBlendModes(SKSPAN_INIT_ONE( SkBlendMode::kSrc )); | |
| result.push_back({ paintOptions, | |
| DrawTypeFlags::kNonAAFillRect, | |
| kRGBA16F_1_D_SRGB }); | |
| } | |
| // Basic SDR YCbCr draws | |
| void basic_sdr(sk_sp<PrecompileShader> sdrImg, | |
| std::vector<PrecompileSettings>& result) { | |
| PaintOptions paintOptions; | |
| paintOptions.setShaders({{ sdrImg }}); | |
| result.push_back({ paintOptions, | |
| kRRectAndNonAARect, | |
| kRGBA_1_D_SRGB }); | |
| // TODO: see if this clipped rect draw can be replaced with an rrect draw | |
| result.push_back({ paintOptions, | |
| DrawTypeFlags::kNonAAFillRect | DrawTypeFlags::kAnalyticClip, | |
| kRGBA_1_D_SRGB }); | |
| paintOptions.setPaintColorIsOpaque(false); | |
| result.push_back({ paintOptions, | |
| DrawTypeFlags::kAnalyticRRect, | |
| kRGBA_1_D_SRGB }); | |
| } | |
| // RE_EdgeExtensionEffect wrapping and SDR YCbCr image | |
| void edge_extension_sdr(RuntimeEffectManager& effectManager, | |
| sk_sp<PrecompileShader> sdrImg, | |
| std::vector<PrecompileSettings>& result) { | |
| sk_sp<PrecompileShader> edgeEffect = wrap_in_edge_extension(effectManager, sdrImg); | |
| PaintOptions paintOptions; | |
| paintOptions.setShaders({{ std::move(edgeEffect) }}); | |
| result.push_back({ paintOptions, | |
| DrawTypeFlags::kNonAAFillRect, | |
| kRGBA_1_D_SRGB }); | |
| paintOptions.setPaintColorIsOpaque(false); | |
| result.push_back({ paintOptions, | |
| DrawTypeFlags::kNonAAFillRect, | |
| kRGBA_1_D_SRGB }); | |
| } | |
| // This method takes a set of YCbCr infos and merges them a set of PaintOptions that Android | |
| // would use for them. The main split is between HDR/SDR handling. HDR handling is much more | |
| // complicated with tone mapping, etc. | |
| void ycbcr_merge(RuntimeEffectManager& effectManager, | |
| SkSpan<const skgpu::VulkanYcbcrConversionInfo> ycbcrs, | |
| SkSpan<const shaders::LinearEffect> linearEffects, | |
| std::vector<PrecompileSettings>& result) { | |
| for (const auto& ycbcr : ycbcrs) { | |
| if (ycbcr.model() == VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020) { | |
| for (const auto& linearEffect : linearEffects) { | |
| // TODO: investigate how Android does this mapping | |
| const SkColorInfo* ci; | |
| if (linearEffect.inputDataspace == ui::Dataspace::BT2020_ITU_PQ) { | |
| ci = &kRGBA8PremulPQ; | |
| } else if (linearEffect.inputDataspace == ui::Dataspace::BT2020_HLG) { | |
| ci = &kRGBA8PremulHLG; | |
| } else { | |
| ci = &kRGBA8Premul2020; | |
| } | |
| sk_sp<PrecompileShader> hdrImg = vulkan_ycbcr_image_shader(ycbcr, *ci); | |
| linear_effect_hdr(effectManager, hdrImg, linearEffect, result); | |
| linear_effect_edge_extension_hdr(effectManager, hdrImg, linearEffect, result); | |
| linear_effect_mourimap_tonemap_hdr(effectManager, hdrImg, result); | |
| mourimap_crosstalk_and_chunk_hdr(effectManager, hdrImg, result); | |
| } | |
| } else { | |
| sk_sp<PrecompileShader> sdrImg = vulkan_ycbcr_image_shader(ycbcr, kRGBA8Premul); | |
| basic_sdr(sdrImg, result); | |
| edge_extension_sdr(effectManager, sdrImg, result); | |
| } | |
| } | |
| } | |
| void VisitAndroidPrecompileSettings_Pixel8( | |
| skgpu::graphite::PrecompileContext* precompileContext, | |
| RuntimeEffectManager& effectManager, | |
| const std::function<void(skgpu::graphite::PrecompileContext*, | |
| const PrecompileSettings&, | |
| int index)>& func) { | |
| static const VkComponentMapping kDefaultComponents = { VK_COMPONENT_SWIZZLE_IDENTITY, | |
| VK_COMPONENT_SWIZZLE_IDENTITY, | |
| VK_COMPONENT_SWIZZLE_IDENTITY, | |
| VK_COMPONENT_SWIZZLE_IDENTITY }; | |
| const skgpu::VulkanYcbcrConversionInfo kPixel8YCbCrs[] = { | |
| { 238, | |
| VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709, | |
| VK_SAMPLER_YCBCR_RANGE_ITU_FULL, | |
| VK_CHROMA_LOCATION_MIDPOINT, | |
| VK_CHROMA_LOCATION_MIDPOINT, | |
| VK_FILTER_LINEAR, | |
| /*forceExplicitReconstruction=*/false, | |
| kDefaultComponents, | |
| VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | |
| }, | |
| { 238, | |
| VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709, | |
| VK_SAMPLER_YCBCR_RANGE_ITU_NARROW, | |
| VK_CHROMA_LOCATION_MIDPOINT, | |
| VK_CHROMA_LOCATION_MIDPOINT, | |
| VK_FILTER_LINEAR, | |
| /*forceExplicitReconstruction=*/false, | |
| kDefaultComponents, | |
| VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | |
| }, | |
| { 238, | |
| VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601, | |
| VK_SAMPLER_YCBCR_RANGE_ITU_NARROW, | |
| VK_CHROMA_LOCATION_MIDPOINT, | |
| VK_CHROMA_LOCATION_MIDPOINT, | |
| VK_FILTER_LINEAR, | |
| /*forceExplicitReconstruction=*/false, | |
| kDefaultComponents, | |
| VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | |
| }, | |
| { 247, | |
| VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020, | |
| VK_SAMPLER_YCBCR_RANGE_ITU_NARROW, | |
| VK_CHROMA_LOCATION_COSITED_EVEN, | |
| VK_CHROMA_LOCATION_COSITED_EVEN, | |
| VK_FILTER_LINEAR, | |
| /*forceExplicitReconstruction=*/false, | |
| kDefaultComponents, | |
| VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | |
| }, | |
| }; | |
| // This specifies the color space information to be used with Rec.2020 YCbCr images. | |
| // TODO: we will need to be able to get this from Android | |
| const shaders::LinearEffect kPixel8LinearEffects[] { | |
| { ui::Dataspace::BT2020_HLG, | |
| ui::Dataspace::UNKNOWN, | |
| false, | |
| ui::Dataspace::UNKNOWN, | |
| shaders::LinearEffect::Shader }, | |
| }; | |
| std::vector<PrecompileSettings> precompileCases; | |
| ycbcr_merge(effectManager, {kPixel8YCbCrs}, {kPixel8LinearEffects}, precompileCases); | |
| for (size_t i = 0; i < std::size(precompileCases); ++i) { | |
| func(precompileContext, precompileCases[i], i); | |
| } | |
| } | |
| } // anonymous namespace | |
| DEF_GRAPHITE_TEST_FOR_VULKAN_CONTEXT(AndroidYCbCrPrecompileTest, reporter, context, | |
| CtsEnforcement::kNever) { | |
| PrecompileTest(reporter, context, kPixel8Cases, VisitAndroidPrecompileSettings_Pixel8, | |
| /* checkPaintOptionCoverage= */ false, | |
| /* checkPipelineLabelCoverage= */ true); | |
| } | |
| #endif |