blob: 54e4c6990072c60c373769e3271ad59b0dc4413c [file] [log] [blame]
/*
* Copyright 2024 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
// This test only works with Graphite.
#include "gm/gm.h"
#include "src/core/SkImageInfoPriv.h"
#if defined(SK_GRAPHITE)
#include "include/core/SkCanvas.h"
#include "include/core/SkColorFilter.h"
#include "include/core/SkPaint.h"
#include "include/core/SkSurface.h"
#include "include/core/SkYUVAInfo.h"
#include "include/effects/SkColorMatrix.h"
#include "include/gpu/graphite/Image.h"
#include "include/gpu/graphite/Recorder.h"
#include "include/gpu/graphite/Surface.h"
#include "src/core/SkYUVAInfoLocation.h"
#include "tools/DecodeUtils.h"
namespace skiagm {
class RenderToMipmappedYUVImagePlanes : public GM {
public:
RenderToMipmappedYUVImagePlanes() { this->setBGColor(0xFFFFFFFF); }
protected:
SkString getName() const override { return SkString("render_to_mipmapped_yuv_image_planes"); }
SkISize getISize() override { return {96, 32}; }
DrawResult onGpuSetup(SkCanvas* canvas, SkString* errorMsg, GraphiteTestContext*) override {
auto* recorder = canvas->recorder();
if (!recorder) {
*errorMsg = "graphite-only test";
return DrawResult::kSkip;
}
if (!fSrcImage) {
fSrcImage = ToolUtils::GetResourceAsImage("images/mandrill_512.png");
if (!fSrcImage) {
*errorMsg = "Could not load src image.";
return DrawResult::kFail;
}
}
return DrawResult::kOk;
}
DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
auto* recorder = canvas->recorder();
if (!recorder) {
*errorMsg = "direct to graphite test";
return DrawResult::kSkip;
}
using PlaneConfig = SkYUVAInfo::PlaneConfig;
using Subsampling = SkYUVAInfo::Subsampling;
struct TestCase {
PlaneConfig config;
Subsampling subsampling;
};
for (const auto& tc : {TestCase{PlaneConfig::kY_U_V, Subsampling::k420},
TestCase{PlaneConfig::kY_UV, Subsampling::k422},
TestCase{PlaneConfig::kYUV, Subsampling::k444}}) {
SkYUVAInfo yuvaInfo(fSrcImage->dimensions(),
tc.config,
tc.subsampling,
kJPEG_Full_SkYUVColorSpace);
float rgbToYuv[20];
SkColorMatrix::RGBtoYUV(yuvaInfo.yuvColorSpace()).getRowMajor(rgbToYuv);
sk_sp<SkImage> planes[SkYUVAInfo::kMaxPlanes];
SkISize dimensions[SkYUVAInfo::kMaxPlanes];
int numPlanes = yuvaInfo.planeDimensions(dimensions);
SkColorType colorTypes [SkYUVAInfo::kMaxPlanes];
uint32_t channelFlags[SkYUVAInfo::kMaxPlanes];
for (int i = 0; i < numPlanes; ++i) {
switch (yuvaInfo.numChannelsInPlane(i)) {
case 1: colorTypes[i] = kAlpha_8_SkColorType; break;
case 2: colorTypes[i] = kR8G8_unorm_SkColorType; break;
case 3: colorTypes[i] = kRGB_888x_SkColorType; break;
case 4: colorTypes[i] = kRGBA_8888_SkColorType; break;
default: SkUNREACHABLE;
}
channelFlags[i] = SkColorTypeChannelFlags(colorTypes[i]);
}
SkYUVAInfo::YUVALocations locations = yuvaInfo.toYUVALocations(channelFlags);
for (int i = 0; i < numPlanes; ++i) {
auto info = SkImageInfo::Make(dimensions[i], colorTypes[i], kPremul_SkAlphaType);
auto surf = SkSurfaces::RenderTarget(recorder, info, skgpu::Mipmapped::kYes);
float matrix[20] {
1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0
};
for (int c = 0; c < SkYUVAInfo::kYUVAChannelCount; ++c) {
if (locations[c].fPlane == i) {
auto d = static_cast<int>(locations[c].fChannel);
std::copy_n(rgbToYuv + 5 * c, 5, matrix + 5 * d);
}
}
auto cf = SkColorFilters::Matrix(matrix);
SkPaint paint;
paint.setColorFilter(SkColorFilters::Matrix(matrix));
surf->getCanvas()->drawImageRect(fSrcImage,
SkRect::Make(surf->imageInfo().dimensions()),
SkFilterMode::kLinear,
&paint);
planes[i] = SkSurfaces::AsImage(std::move(surf));
}
auto yuvaImage = SkImages::TextureFromYUVAImages(recorder,
yuvaInfo,
planes,
/*imageColorSpace=*/nullptr);
auto dstRect = SkRect::MakeWH(yuvaImage->width() / 16.f, yuvaImage->height() / 16.f);
canvas->drawImageRect(yuvaImage.get(),
dstRect,
SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear));
canvas->translate(std::ceil(dstRect.width()), 0);
}
return DrawResult::kOk;
}
private:
sk_sp<SkImage> fSrcImage;
};
DEF_GM(return new RenderToMipmappedYUVImagePlanes();)
} // namespace skiagm
#endif