| /* |
| * Copyright 2022 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/SkCanvas.h" |
| #include "include/core/SkPixmap.h" |
| #include "include/gpu/graphite/Context.h" |
| #include "include/gpu/graphite/Recorder.h" |
| #include "include/gpu/graphite/Recording.h" |
| #include "src/gpu/graphite/Surface_Graphite.h" |
| |
| namespace skgpu::graphite { |
| |
| using DrawCallback = std::function<void(SkCanvas*)>; |
| |
| struct Expectation { |
| int fX; |
| int fY; |
| SkColor4f fColor; |
| }; |
| |
| void run_test(skiatest::Reporter* reporter, |
| Context* context, |
| SkISize surfaceSize, |
| SkISize recordingSize, |
| SkISize replayOffset, |
| DrawCallback draw, |
| const std::vector<Expectation>& expectations) { |
| const SkImageInfo surfaceImageInfo = SkImageInfo::Make( |
| surfaceSize, SkColorType::kRGBA_8888_SkColorType, SkAlphaType::kPremul_SkAlphaType); |
| |
| std::unique_ptr<Recorder> surfaceRecorder = context->makeRecorder(); |
| sk_sp<SkSurface> surface = SkSurface::MakeGraphite(surfaceRecorder.get(), surfaceImageInfo); |
| Surface* graphiteSurface = static_cast<Surface*>(surface.get()); |
| const TextureInfo& textureInfo = graphiteSurface->backingTextureProxy()->textureInfo(); |
| |
| // Flush the initial clear added by MakeGraphite. |
| std::unique_ptr<skgpu::graphite::Recording> surfaceRecording = surfaceRecorder->snap(); |
| context->insertRecording({surfaceRecording.get()}); |
| |
| // Snap a recording without a bound target. |
| const SkImageInfo recordingImageInfo = surfaceImageInfo.makeDimensions(recordingSize); |
| std::unique_ptr<Recorder> recorder = context->makeRecorder(); |
| SkCanvas* canvas = recorder->makeDeferredCanvas(recordingImageInfo, textureInfo); |
| draw(canvas); |
| |
| // Can't make another canvas before snapping. |
| REPORTER_ASSERT(reporter, |
| recorder->makeDeferredCanvas(recordingImageInfo, textureInfo) == nullptr); |
| std::unique_ptr<Recording> recording = recorder->snap(); |
| |
| // Play back recording. |
| context->insertRecording( |
| {recording.get(), surface.get(), {replayOffset.fWidth, replayOffset.fHeight}}); |
| |
| // Read pixels. |
| SkBitmap bitmap; |
| SkPixmap pixmap; |
| bitmap.allocPixels(surfaceImageInfo); |
| SkAssertResult(bitmap.peekPixels(&pixmap)); |
| if (!surface->readPixels(pixmap, 0, 0)) { |
| ERRORF(reporter, "readPixels failed"); |
| return; |
| } |
| |
| // Veryify expectations are met and recording is uninstantiated. |
| REPORTER_ASSERT(reporter, !recording->isTargetProxyInstantiated()); |
| for (const Expectation& e : expectations) { |
| SkColor4f color = pixmap.getColor4f(e.fX, e.fY); |
| #ifdef SK_DEBUG |
| if (color != e.fColor) { |
| SkDebugf("Wrong color\n\texpected: %f %f %f %f\n\tactual: %f %f %f %f", |
| color.fR, |
| color.fG, |
| color.fB, |
| color.fA, |
| e.fColor.fR, |
| e.fColor.fG, |
| e.fColor.fB, |
| e.fColor.fA); |
| } |
| #endif |
| REPORTER_ASSERT(reporter, color == e.fColor); |
| } |
| } |
| |
| // Tests that clear does not clear an entire replayed-to surface if recorded onto a smaller surface. |
| DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(RecordingSurfacesTestClear, reporter, context) { |
| SkISize surfaceSize = SkISize::Make(8, 4); |
| SkISize recordingSize = SkISize::Make(4, 4); |
| SkISize replayOffset = SkISize::Make(0, 0); |
| |
| auto draw = [](SkCanvas* canvas) { canvas->clear(SkColors::kRed); }; |
| |
| std::vector<Expectation> expectations = {{0, 0, SkColors::kRed}, |
| {4, 0, SkColors::kTransparent}}; |
| |
| run_test(reporter, context, surfaceSize, recordingSize, replayOffset, draw, expectations); |
| } |
| |
| // Tests that writePixels is translated correctly when replayed with an offset. |
| DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(RecordingSurfacesTestWritePixels, reporter, context) { |
| SkBitmap bitmap; |
| bitmap.allocN32Pixels(4, 4, true); |
| SkCanvas bitmapCanvas(bitmap); |
| SkPaint paint; |
| paint.setColor(SkColors::kRed); |
| bitmapCanvas.drawIRect(SkIRect::MakeXYWH(0, 0, 4, 4), paint); |
| |
| SkISize surfaceSize = SkISize::Make(8, 4); |
| SkISize recordingSize = SkISize::Make(4, 4); |
| SkISize replayOffset = SkISize::Make(4, 0); |
| |
| auto draw = [&bitmap](SkCanvas* canvas) { canvas->writePixels(bitmap, 0, 0); }; |
| |
| std::vector<Expectation> expectations = {{0, 0, SkColors::kTransparent}, |
| {4, 0, SkColors::kRed}}; |
| |
| run_test(reporter, context, surfaceSize, recordingSize, replayOffset, draw, expectations); |
| } |
| |
| // Tests that the result of writePixels is cropped correctly when offscreen. |
| DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(RecordingSurfacesTestWritePixelsOffscreen, reporter, context) { |
| SkBitmap bitmap; |
| bitmap.allocN32Pixels(4, 4, true); |
| SkCanvas bitmapCanvas(bitmap); |
| SkPaint paint; |
| paint.setColor(SkColors::kRed); |
| bitmapCanvas.drawIRect(SkIRect::MakeXYWH(0, 0, 4, 4), paint); |
| paint.setColor(SkColors::kGreen); |
| bitmapCanvas.drawIRect(SkIRect::MakeXYWH(2, 2, 2, 2), paint); |
| |
| SkISize surfaceSize = SkISize::Make(4, 4); |
| SkISize recordingSize = SkISize::Make(4, 4); |
| SkISize replayOffset = SkISize::Make(-2, -2); |
| |
| auto draw = [&bitmap](SkCanvas* canvas) { canvas->writePixels(bitmap, 0, 0); }; |
| |
| std::vector<Expectation> expectations = {{0, 0, SkColors::kGreen}}; |
| |
| run_test(reporter, context, surfaceSize, recordingSize, replayOffset, draw, expectations); |
| } |
| |
| } // namespace skgpu::graphite |