1/* 2 * Copyright 2019 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "include/gpu/ganesh/GrDirectContext.h" 9#include "include/gpu/ganesh/mtl/GrMtlBackendSurface.h" 10#include "src/gpu/ganesh/GrDirectContextPriv.h" 11#include "src/gpu/ganesh/mtl/GrMtlCaps.h" 12#include "tests/Test.h" 13#include "tools/gpu/ManagedBackendTexture.h" 14 15#import <Metal/Metal.h> 16 17using sk_gpu_test::ManagedBackendTexture; 18 19// In BackendAllocationTest.cpp 20void test_wrapping(GrDirectContext*, 21 skiatest::Reporter*, 22 const std::function<sk_sp<ManagedBackendTexture>( 23 GrDirectContext*, skgpu::Mipmapped, GrRenderable)>& create, 24 GrColorType, 25 skgpu::Mipmapped, 26 GrRenderable); 27 28void test_color_init( 29 GrDirectContext*, 30 skiatest::Reporter*, 31 const std::function<sk_sp<ManagedBackendTexture>( 32 GrDirectContext*, const SkColor4f&, skgpu::Mipmapped, GrRenderable)>& create, 33 GrColorType, 34 const SkColor4f&, 35 skgpu::Mipmapped, 36 GrRenderable); 37 38void test_pixmap_init(GrDirectContext*, 39 skiatest::Reporter*, 40 const std::function<sk_sp<ManagedBackendTexture>(GrDirectContext*, 41 const SkPixmap srcData[], 42 int numLevels, 43 GrSurfaceOrigin, 44 GrRenderable)>& create, 45 SkColorType, 46 GrSurfaceOrigin, 47 skgpu::Mipmapped, 48 GrRenderable); 49 50DEF_GANESH_TEST_FOR_METAL_CONTEXT(MtlBackendAllocationTest, reporter, ctxInfo) { 51 auto dContext = ctxInfo.directContext(); 52 const GrMtlCaps* mtlCaps = static_cast<const GrMtlCaps*>(dContext->priv().caps()); 53 54 constexpr SkColor4f kTransCol { 0, 0.25f, 0.75f, 0.5f }; 55 constexpr SkColor4f kGrayCol { 0.75f, 0.75f, 0.75f, 0.75f }; 56 57 struct { 58 GrColorType fColorType; 59 MTLPixelFormat fFormat; 60 SkColor4f fColor; 61 } combinations[] = { 62 { GrColorType::kRGBA_8888, MTLPixelFormatRGBA8Unorm, SkColors::kRed }, 63 { GrColorType::kRGBA_8888_SRGB, MTLPixelFormatRGBA8Unorm_sRGB, SkColors::kRed }, 64 65 // In this configuration (i.e., an RGB_888x colortype with an RGBA8 backing format), 66 // there is nothing to tell Skia to make the provided color opaque. Clients will need 67 // to provide an opaque initialization color in this case. 68 { GrColorType::kRGB_888x, MTLPixelFormatRGBA8Unorm, SkColors::kYellow }, 69 70 { GrColorType::kBGRA_8888, MTLPixelFormatBGRA8Unorm, SkColors::kBlue }, 71 72 { GrColorType::kRGBA_1010102, MTLPixelFormatRGB10A2Unorm, 73 { 0.25f, 0.5f, 0.75f, 1.0f } }, 74 { GrColorType::kRGB_101010x, MTLPixelFormatRGB10A2Unorm, 75 { 0.25f, 0.5f, 0.75f, 1.0f } }, 76#ifdef SK_BUILD_FOR_MAC 77 { GrColorType::kBGRA_1010102, MTLPixelFormatBGR10A2Unorm, 78 { 0.25f, 0.5f, 0.75f, 1.0f } }, 79#endif 80#ifdef SK_BUILD_FOR_IOS 81 { GrColorType::kBGR_565, MTLPixelFormatB5G6R5Unorm, SkColors::kRed }, 82 { GrColorType::kABGR_4444, MTLPixelFormatABGR4Unorm, SkColors::kGreen }, 83#endif 84 85 { GrColorType::kAlpha_8, MTLPixelFormatA8Unorm, kTransCol }, 86 { GrColorType::kAlpha_8, MTLPixelFormatR8Unorm, kTransCol }, 87 { GrColorType::kGray_8, MTLPixelFormatR8Unorm, kGrayCol }, 88 89 { GrColorType::kRGBA_F16_Clamped, MTLPixelFormatRGBA16Float, SkColors::kLtGray }, 90 { GrColorType::kRGBA_F16, MTLPixelFormatRGBA16Float, SkColors::kYellow }, 91 { GrColorType::kRGB_F16F16F16x, MTLPixelFormatRGBA16Float, SkColors::kYellow }, 92 93 { GrColorType::kRG_88, MTLPixelFormatRG8Unorm, { 0.5f, 0.5f, 0, 1 } }, 94 { GrColorType::kAlpha_F16, MTLPixelFormatR16Float, { 1.0f, 0, 0, 0.5f } }, 95 96 { GrColorType::kAlpha_16, MTLPixelFormatR16Unorm, kTransCol }, 97 { GrColorType::kRG_1616, MTLPixelFormatRG16Unorm, SkColors::kYellow }, 98 99 { GrColorType::kRGBA_16161616, MTLPixelFormatRGBA16Unorm, SkColors::kLtGray }, 100 { GrColorType::kRG_F16, MTLPixelFormatRG16Float, SkColors::kYellow }, 101 }; 102 103 for (auto combo : combinations) { 104 GrBackendFormat format = GrBackendFormats::MakeMtl(combo.fFormat); 105 106 if (!mtlCaps->isFormatTexturable(combo.fFormat)) { 107 continue; 108 } 109 110 // skbug.com/9086 (Metal caps may not be handling RGBA32 correctly) 111 if (GrColorType::kRGBA_F32 == combo.fColorType) { 112 continue; 113 } 114 115 for (auto mipmapped : {skgpu::Mipmapped::kNo, skgpu::Mipmapped::kYes}) { 116 if (skgpu::Mipmapped::kYes == mipmapped && !mtlCaps->mipmapSupport()) { 117 continue; 118 } 119 120 for (auto renderable : { GrRenderable::kNo, GrRenderable::kYes }) { 121 122 if (GrRenderable::kYes == renderable) { 123 // We must also check whether we allow rendering to the format using the 124 // color type. 125 if (!mtlCaps->isFormatAsColorTypeRenderable( 126 combo.fColorType, GrBackendFormats::MakeMtl(combo.fFormat), 1)) { 127 continue; 128 } 129 } 130 131 { 132 auto uninitCreateMtd = [format](GrDirectContext* dContext, 133 skgpu::Mipmapped mipmapped, 134 GrRenderable renderable) { 135 return ManagedBackendTexture::MakeWithoutData(dContext, 136 32, 32, 137 format, 138 mipmapped, 139 renderable, 140 GrProtected::kNo); 141 }; 142 143 test_wrapping(dContext, reporter, uninitCreateMtd, combo.fColorType, mipmapped, 144 renderable); 145 } 146 147 { 148 // We're creating backend textures without specifying a color type "view" of 149 // them at the public API level. Therefore, Ganesh will not apply any swizzles 150 // before writing the color to the texture. However, our validation code does 151 // rely on interpreting the texture contents via a SkColorType and therefore 152 // swizzles may be applied during the read step. 153 // Ideally we'd update our validation code to use a "raw" read that doesn't 154 // impose a color type but for now we just munge the data we upload to match the 155 // expectation. 156 skgpu::Swizzle swizzle; 157 switch (combo.fColorType) { 158 case GrColorType::kAlpha_8: 159 swizzle = skgpu::Swizzle("aaaa"); 160 break; 161 case GrColorType::kAlpha_16: 162 swizzle = skgpu::Swizzle("aaaa"); 163 break; 164 case GrColorType::kAlpha_F16: 165 swizzle = skgpu::Swizzle("aaaa"); 166 break; 167 default: 168 break; 169 } 170 171 auto createWithColorMtd = [format, swizzle](GrDirectContext* dContext, 172 const SkColor4f& color, 173 skgpu::Mipmapped mipmapped, 174 GrRenderable renderable) { 175 auto swizzledColor = swizzle.applyTo(color); 176 return ManagedBackendTexture::MakeWithData(dContext, 177 32, 32, 178 format, 179 swizzledColor, 180 mipmapped, 181 renderable, 182 GrProtected::kNo); 183 }; 184 test_color_init(dContext, reporter, createWithColorMtd, combo.fColorType, 185 combo.fColor, mipmapped, renderable); 186 } 187 188 for (auto origin : {kTopLeft_GrSurfaceOrigin, kBottomLeft_GrSurfaceOrigin}) { 189 SkColorType skColorType = GrColorTypeToSkColorType(combo.fColorType); 190 if (skColorType == kUnknown_SkColorType) { 191 break; 192 } 193 194 auto createWithSrcDataMtd = [](GrDirectContext* dContext, 195 const SkPixmap srcData[], 196 int numLevels, 197 GrSurfaceOrigin origin, 198 GrRenderable renderable) { 199 SkASSERT(srcData && numLevels); 200 return ManagedBackendTexture::MakeWithData(dContext, 201 srcData, 202 numLevels, 203 origin, 204 renderable, 205 GrProtected::kNo); 206 }; 207 208 test_pixmap_init(dContext, 209 reporter, 210 createWithSrcDataMtd, 211 skColorType, 212 origin, 213 mipmapped, 214 renderable); 215 216 } 217 } 218 } 219 } 220} 221