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