/* * Copyright 2023 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" #include "include/core/SkBitmap.h" #include "include/core/SkColorSpace.h" #include "include/core/SkRect.h" #include "include/core/SkTileMode.h" #include "include/gpu/graphite/Context.h" #include "include/gpu/graphite/Image.h" #include "include/gpu/graphite/Surface.h" #include "src/gpu/graphite/Caps.h" #include "src/gpu/graphite/ContextPriv.h" #include "src/gpu/graphite/Surface_Graphite.h" #include "src/shaders/SkImageShader.h" #include "tools/ToolUtils.h" #include "tools/gpu/ManagedBackendTexture.h" namespace skgpu::graphite { namespace { using DrawFn = void (*)(sk_sp, SkCanvas*, SkRect /*srcRect*/, SkRect /*dstRect*/); constexpr SkColor4f kTopColor = SkColors::kRed; constexpr SkColor4f kBottomColor = SkColors::kBlue; constexpr int32_t kHalfSize = 4; constexpr SkISize kImageSize = {2*kHalfSize, 2*kHalfSize}; void test_draw(skiatest::Reporter* reporter, Context* context, skgpu::Origin origin, SkRect srcRect, SkRect dstRect, DrawFn drawImageFn) { std::unique_ptr recorder = context->makeRecorder(); skgpu::Protected isProtected = skgpu::Protected(context->priv().caps()->protectedSupport()); SkBitmap bitmap; bitmap.allocPixels(SkImageInfo::Make(kImageSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType), 0); bitmap.eraseColor(kTopColor); bitmap.erase(kBottomColor, SkIRect::MakeLTRB(0, kHalfSize, kImageSize.width(), kImageSize.height())); auto managedTexture = sk_gpu_test::ManagedGraphiteTexture::MakeFromPixmap(recorder.get(), bitmap.pixmap(), skgpu::Mipmapped::kNo, skgpu::Renderable::kNo, isProtected); REPORTER_ASSERT(reporter, managedTexture); if (!managedTexture) { return; } sk_sp image = SkImages::WrapTexture(recorder.get(), managedTexture->texture(), kRGBA_8888_SkColorType, kPremul_SkAlphaType, /*colorSpace=*/nullptr, origin); REPORTER_ASSERT(reporter, image); if (!image) { return; } sk_sp surface = SkSurfaces::RenderTarget( recorder.get(), SkImageInfo::Make(kImageSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType)); REPORTER_ASSERT(reporter, surface); if (!surface) { return; } SkCanvas* canvas = surface->getCanvas(); drawImageFn(image, canvas, srcRect, dstRect); SkPixmap pm; SkBitmap result; result.allocPixels(SkImageInfo::Make(kImageSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType)); bool peekPixelsSuccess = result.peekPixels(&pm); REPORTER_ASSERT(reporter, peekPixelsSuccess); bool readPixelsSuccess = surface->readPixels(pm, 0, 0); REPORTER_ASSERT(reporter, readPixelsSuccess); bool resultTopColorOnTop = origin == skgpu::Origin::kTopLeft; for (int32_t y = 0; y < kImageSize.height(); ++y) { for (int32_t x = 0; x < kImageSize.width(); ++x) { SkColor4f color = pm.getColor4f(x, y); SkColor4f expectedColor = ((y < kHalfSize) == resultTopColorOnTop) ? kTopColor : kBottomColor; REPORTER_ASSERT(reporter, color == expectedColor, "At position {%d, %d}, " "expected {%.1f, %.1f, %.1f, %.1f}, " "found {%.1f, %.1f, %.1f, %.1f}", x, y, expectedColor.fR, expectedColor.fG, expectedColor.fB, expectedColor.fA, color.fR, color.fG, color.fB, color.fA); } } } const SkRect kTestSrcRects[] = { // entire thing SkRect::MakeWH(kImageSize.width(), kImageSize.height()), // half rect still splitting top and bottom colors SkRect::MakeXYWH(2, 2, kHalfSize, kHalfSize), }; void test_draw_fn(skiatest::Reporter* reporter, Context* context, DrawFn drawImageFn) { for (auto origin : {skgpu::Origin::kTopLeft, skgpu::Origin::kBottomLeft}) { for (auto srcRect: kTestSrcRects) { test_draw(reporter, context, origin, srcRect, SkRect::MakeWH(kImageSize.width(), kImageSize.height()), drawImageFn); } } } void draw_image(sk_sp image, SkCanvas* canvas, SkRect srcRect, SkRect dstRect) { canvas->drawImageRect(image, srcRect, dstRect, SkSamplingOptions(), /*paint=*/nullptr, SkCanvas::kStrict_SrcRectConstraint); } void draw_image_with_shader(sk_sp image, SkCanvas* canvas, SkRect srcRect, SkRect dstRect) { SkPaint p; SkMatrix srcToDst = SkMatrix::RectToRect(srcRect, dstRect); p.setShader(SkImageShader::MakeSubset( std::move(image), srcRect, SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions(), &srcToDst)); canvas->drawRect(dstRect, p); } } // anonymous namespace DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(ImageOriginTest_drawImage_Graphite, reporter, context, CtsEnforcement::kApiLevel_V) { test_draw_fn(reporter, context, draw_image); } DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(ImageOriginTest_imageShader_Graphite, reporter, context, CtsEnforcement::kApiLevel_V) { test_draw_fn(reporter, context, draw_image_with_shader); } } // namespace skgpu::graphite