1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2024 Google LLC 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker // This test only works with Graphite. 9*c8dee2aaSAndroid Build Coastguard Worker 10*c8dee2aaSAndroid Build Coastguard Worker #include "gm/gm.h" 11*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkImageInfoPriv.h" 12*c8dee2aaSAndroid Build Coastguard Worker 13*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GRAPHITE) 14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorFilter.h" 16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h" 17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h" 18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkYUVAInfo.h" 19*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkColorMatrix.h" 20*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Image.h" 21*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Recorder.h" 22*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Surface.h" 23*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkYUVAInfoLocation.h" 24*c8dee2aaSAndroid Build Coastguard Worker #include "tools/DecodeUtils.h" 25*c8dee2aaSAndroid Build Coastguard Worker 26*c8dee2aaSAndroid Build Coastguard Worker namespace skiagm { 27*c8dee2aaSAndroid Build Coastguard Worker class RenderToMipmappedYUVImagePlanes : public GM { 28*c8dee2aaSAndroid Build Coastguard Worker public: RenderToMipmappedYUVImagePlanes()29*c8dee2aaSAndroid Build Coastguard Worker RenderToMipmappedYUVImagePlanes() { this->setBGColor(0xFFFFFFFF); } 30*c8dee2aaSAndroid Build Coastguard Worker 31*c8dee2aaSAndroid Build Coastguard Worker protected: getName() const32*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override { return SkString("render_to_mipmapped_yuv_image_planes"); } 33*c8dee2aaSAndroid Build Coastguard Worker getISize()34*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override { return {96, 32}; } 35*c8dee2aaSAndroid Build Coastguard Worker onGpuSetup(SkCanvas * canvas,SkString * errorMsg,GraphiteTestContext *)36*c8dee2aaSAndroid Build Coastguard Worker DrawResult onGpuSetup(SkCanvas* canvas, SkString* errorMsg, GraphiteTestContext*) override { 37*c8dee2aaSAndroid Build Coastguard Worker auto* recorder = canvas->recorder(); 38*c8dee2aaSAndroid Build Coastguard Worker if (!recorder) { 39*c8dee2aaSAndroid Build Coastguard Worker *errorMsg = "graphite-only test"; 40*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kSkip; 41*c8dee2aaSAndroid Build Coastguard Worker } 42*c8dee2aaSAndroid Build Coastguard Worker if (!fSrcImage) { 43*c8dee2aaSAndroid Build Coastguard Worker fSrcImage = ToolUtils::GetResourceAsImage("images/mandrill_512.png"); 44*c8dee2aaSAndroid Build Coastguard Worker if (!fSrcImage) { 45*c8dee2aaSAndroid Build Coastguard Worker *errorMsg = "Could not load src image."; 46*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kFail; 47*c8dee2aaSAndroid Build Coastguard Worker } 48*c8dee2aaSAndroid Build Coastguard Worker } 49*c8dee2aaSAndroid Build Coastguard Worker 50*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kOk; 51*c8dee2aaSAndroid Build Coastguard Worker } 52*c8dee2aaSAndroid Build Coastguard Worker onDraw(SkCanvas * canvas,SkString * errorMsg)53*c8dee2aaSAndroid Build Coastguard Worker DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override { 54*c8dee2aaSAndroid Build Coastguard Worker auto* recorder = canvas->recorder(); 55*c8dee2aaSAndroid Build Coastguard Worker if (!recorder) { 56*c8dee2aaSAndroid Build Coastguard Worker *errorMsg = "direct to graphite test"; 57*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kSkip; 58*c8dee2aaSAndroid Build Coastguard Worker } 59*c8dee2aaSAndroid Build Coastguard Worker using PlaneConfig = SkYUVAInfo::PlaneConfig; 60*c8dee2aaSAndroid Build Coastguard Worker using Subsampling = SkYUVAInfo::Subsampling; 61*c8dee2aaSAndroid Build Coastguard Worker struct TestCase { 62*c8dee2aaSAndroid Build Coastguard Worker PlaneConfig config; 63*c8dee2aaSAndroid Build Coastguard Worker Subsampling subsampling; 64*c8dee2aaSAndroid Build Coastguard Worker }; 65*c8dee2aaSAndroid Build Coastguard Worker for (const auto& tc : {TestCase{PlaneConfig::kY_U_V, Subsampling::k420}, 66*c8dee2aaSAndroid Build Coastguard Worker TestCase{PlaneConfig::kY_UV, Subsampling::k422}, 67*c8dee2aaSAndroid Build Coastguard Worker TestCase{PlaneConfig::kYUV, Subsampling::k444}}) { 68*c8dee2aaSAndroid Build Coastguard Worker SkYUVAInfo yuvaInfo(fSrcImage->dimensions(), 69*c8dee2aaSAndroid Build Coastguard Worker tc.config, 70*c8dee2aaSAndroid Build Coastguard Worker tc.subsampling, 71*c8dee2aaSAndroid Build Coastguard Worker kJPEG_Full_SkYUVColorSpace); 72*c8dee2aaSAndroid Build Coastguard Worker 73*c8dee2aaSAndroid Build Coastguard Worker float rgbToYuv[20]; 74*c8dee2aaSAndroid Build Coastguard Worker SkColorMatrix::RGBtoYUV(yuvaInfo.yuvColorSpace()).getRowMajor(rgbToYuv); 75*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> planes[SkYUVAInfo::kMaxPlanes]; 76*c8dee2aaSAndroid Build Coastguard Worker SkISize dimensions[SkYUVAInfo::kMaxPlanes]; 77*c8dee2aaSAndroid Build Coastguard Worker int numPlanes = yuvaInfo.planeDimensions(dimensions); 78*c8dee2aaSAndroid Build Coastguard Worker 79*c8dee2aaSAndroid Build Coastguard Worker SkColorType colorTypes [SkYUVAInfo::kMaxPlanes]; 80*c8dee2aaSAndroid Build Coastguard Worker uint32_t channelFlags[SkYUVAInfo::kMaxPlanes]; 81*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < numPlanes; ++i) { 82*c8dee2aaSAndroid Build Coastguard Worker switch (yuvaInfo.numChannelsInPlane(i)) { 83*c8dee2aaSAndroid Build Coastguard Worker case 1: colorTypes[i] = kAlpha_8_SkColorType; break; 84*c8dee2aaSAndroid Build Coastguard Worker case 2: colorTypes[i] = kR8G8_unorm_SkColorType; break; 85*c8dee2aaSAndroid Build Coastguard Worker case 3: colorTypes[i] = kRGB_888x_SkColorType; break; 86*c8dee2aaSAndroid Build Coastguard Worker case 4: colorTypes[i] = kRGBA_8888_SkColorType; break; 87*c8dee2aaSAndroid Build Coastguard Worker 88*c8dee2aaSAndroid Build Coastguard Worker default: SkUNREACHABLE; 89*c8dee2aaSAndroid Build Coastguard Worker } 90*c8dee2aaSAndroid Build Coastguard Worker channelFlags[i] = SkColorTypeChannelFlags(colorTypes[i]); 91*c8dee2aaSAndroid Build Coastguard Worker } 92*c8dee2aaSAndroid Build Coastguard Worker SkYUVAInfo::YUVALocations locations = yuvaInfo.toYUVALocations(channelFlags); 93*c8dee2aaSAndroid Build Coastguard Worker 94*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < numPlanes; ++i) { 95*c8dee2aaSAndroid Build Coastguard Worker auto info = SkImageInfo::Make(dimensions[i], colorTypes[i], kPremul_SkAlphaType); 96*c8dee2aaSAndroid Build Coastguard Worker auto surf = SkSurfaces::RenderTarget(recorder, info, skgpu::Mipmapped::kYes); 97*c8dee2aaSAndroid Build Coastguard Worker if (!surf) { 98*c8dee2aaSAndroid Build Coastguard Worker continue; 99*c8dee2aaSAndroid Build Coastguard Worker } 100*c8dee2aaSAndroid Build Coastguard Worker 101*c8dee2aaSAndroid Build Coastguard Worker float matrix[20] { 102*c8dee2aaSAndroid Build Coastguard Worker 1, 0, 0, 0, 0, 103*c8dee2aaSAndroid Build Coastguard Worker 0, 1, 0, 0, 0, 104*c8dee2aaSAndroid Build Coastguard Worker 0, 0, 1, 0, 0, 105*c8dee2aaSAndroid Build Coastguard Worker 0, 0, 0, 1, 0 106*c8dee2aaSAndroid Build Coastguard Worker }; 107*c8dee2aaSAndroid Build Coastguard Worker 108*c8dee2aaSAndroid Build Coastguard Worker for (int c = 0; c < SkYUVAInfo::kYUVAChannelCount; ++c) { 109*c8dee2aaSAndroid Build Coastguard Worker if (locations[c].fPlane == i) { 110*c8dee2aaSAndroid Build Coastguard Worker auto d = static_cast<int>(locations[c].fChannel); 111*c8dee2aaSAndroid Build Coastguard Worker std::copy_n(rgbToYuv + 5 * c, 5, matrix + 5 * d); 112*c8dee2aaSAndroid Build Coastguard Worker } 113*c8dee2aaSAndroid Build Coastguard Worker } 114*c8dee2aaSAndroid Build Coastguard Worker 115*c8dee2aaSAndroid Build Coastguard Worker auto cf = SkColorFilters::Matrix(matrix); 116*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint; 117*c8dee2aaSAndroid Build Coastguard Worker paint.setColorFilter(SkColorFilters::Matrix(matrix)); 118*c8dee2aaSAndroid Build Coastguard Worker surf->getCanvas()->drawImageRect(fSrcImage, 119*c8dee2aaSAndroid Build Coastguard Worker SkRect::Make(surf->imageInfo().dimensions()), 120*c8dee2aaSAndroid Build Coastguard Worker SkFilterMode::kLinear, 121*c8dee2aaSAndroid Build Coastguard Worker &paint); 122*c8dee2aaSAndroid Build Coastguard Worker planes[i] = SkSurfaces::AsImage(std::move(surf)); 123*c8dee2aaSAndroid Build Coastguard Worker } 124*c8dee2aaSAndroid Build Coastguard Worker auto yuvaImage = SkImages::TextureFromYUVAImages(recorder, 125*c8dee2aaSAndroid Build Coastguard Worker yuvaInfo, 126*c8dee2aaSAndroid Build Coastguard Worker planes, 127*c8dee2aaSAndroid Build Coastguard Worker /*imageColorSpace=*/nullptr); 128*c8dee2aaSAndroid Build Coastguard Worker if (yuvaImage) { 129*c8dee2aaSAndroid Build Coastguard Worker auto dstRect = SkRect::MakeWH(yuvaImage->width() / 16.f, 130*c8dee2aaSAndroid Build Coastguard Worker yuvaImage->height() / 16.f); 131*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImageRect(yuvaImage.get(), 132*c8dee2aaSAndroid Build Coastguard Worker dstRect, 133*c8dee2aaSAndroid Build Coastguard Worker SkSamplingOptions(SkFilterMode::kLinear, 134*c8dee2aaSAndroid Build Coastguard Worker SkMipmapMode::kLinear)); 135*c8dee2aaSAndroid Build Coastguard Worker } 136*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(std::ceil(yuvaInfo.width()/16.f), 0); 137*c8dee2aaSAndroid Build Coastguard Worker } 138*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kOk; 139*c8dee2aaSAndroid Build Coastguard Worker } 140*c8dee2aaSAndroid Build Coastguard Worker 141*c8dee2aaSAndroid Build Coastguard Worker private: 142*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> fSrcImage; 143*c8dee2aaSAndroid Build Coastguard Worker }; 144*c8dee2aaSAndroid Build Coastguard Worker 145*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new RenderToMipmappedYUVImagePlanes();) 146*c8dee2aaSAndroid Build Coastguard Worker } // namespace skiagm 147*c8dee2aaSAndroid Build Coastguard Worker #endif 148