| /* |
| * 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<SkImage>, 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> 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<SkImage> image = SkImages::WrapTexture(recorder.get(), |
| managedTexture->texture(), |
| kRGBA_8888_SkColorType, |
| kPremul_SkAlphaType, |
| /*colorSpace=*/nullptr, |
| origin); |
| |
| REPORTER_ASSERT(reporter, image); |
| if (!image) { |
| return; |
| } |
| |
| sk_sp<SkSurface> 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<SkImage> 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<SkImage> 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::kNextRelease) { |
| test_draw_fn(reporter, context, draw_image); |
| } |
| |
| DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(ImageOriginTest_imageShader_Graphite, reporter, context, |
| CtsEnforcement::kNextRelease) { |
| test_draw_fn(reporter, context, draw_image_with_shader); |
| } |
| |
| } // namespace skgpu::graphite |