1 /*
2 * Copyright 2022 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "tests/Test.h"
9
10 #include "include/core/SkBitmap.h"
11 #include "include/core/SkCanvas.h"
12 #include "include/core/SkPixmap.h"
13 #include "include/gpu/graphite/Context.h"
14 #include "include/gpu/graphite/Recorder.h"
15 #include "include/gpu/graphite/Recording.h"
16 #include "include/gpu/graphite/Surface.h"
17 #include "src/gpu/graphite/RecordingPriv.h"
18 #include "src/gpu/graphite/Surface_Graphite.h"
19
20 namespace skgpu::graphite {
21
22 using DrawCallback = std::function<void(SkCanvas*)>;
23
24 struct Expectation {
25 int fX;
26 int fY;
27 SkColor4f fColor;
28 };
29
run_test(skiatest::Reporter * reporter,Context * context,SkISize surfaceSize,SkISize recordingSize,SkISize replayOffset,DrawCallback draw,const std::vector<Expectation> & expectations)30 void run_test(skiatest::Reporter* reporter,
31 Context* context,
32 SkISize surfaceSize,
33 SkISize recordingSize,
34 SkISize replayOffset,
35 DrawCallback draw,
36 const std::vector<Expectation>& expectations) {
37 const SkImageInfo surfaceImageInfo = SkImageInfo::Make(
38 surfaceSize, SkColorType::kRGBA_8888_SkColorType, SkAlphaType::kPremul_SkAlphaType);
39
40 std::unique_ptr<Recorder> surfaceRecorder = context->makeRecorder();
41 sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(surfaceRecorder.get(), surfaceImageInfo);
42 Surface* graphiteSurface = static_cast<Surface*>(surface.get());
43 const TextureInfo& textureInfo = graphiteSurface->backingTextureProxy()->textureInfo();
44
45 // Flush the initial clear added by MakeGraphite.
46 std::unique_ptr<skgpu::graphite::Recording> surfaceRecording = surfaceRecorder->snap();
47 context->insertRecording({surfaceRecording.get()});
48
49 // Snap a recording without a bound target.
50 const SkImageInfo recordingImageInfo = surfaceImageInfo.makeDimensions(recordingSize);
51 std::unique_ptr<Recorder> recorder = context->makeRecorder();
52 SkCanvas* canvas = recorder->makeDeferredCanvas(recordingImageInfo, textureInfo);
53 draw(canvas);
54
55 // Can't make another canvas before snapping.
56 REPORTER_ASSERT(reporter,
57 recorder->makeDeferredCanvas(recordingImageInfo, textureInfo) == nullptr);
58 std::unique_ptr<Recording> recording = recorder->snap();
59
60 // Play back recording.
61 context->insertRecording(
62 {recording.get(), surface.get(), {replayOffset.fWidth, replayOffset.fHeight}});
63
64 // Read pixels.
65 SkBitmap bitmap;
66 SkPixmap pixmap;
67 bitmap.allocPixels(surfaceImageInfo);
68 SkAssertResult(bitmap.peekPixels(&pixmap));
69 if (!surface->readPixels(pixmap, 0, 0)) {
70 ERRORF(reporter, "readPixels failed");
71 return;
72 }
73
74 // Veryify expectations are met and recording is uninstantiated.
75 REPORTER_ASSERT(reporter, !recording->priv().isTargetProxyInstantiated());
76 for (const Expectation& e : expectations) {
77 SkColor4f color = pixmap.getColor4f(e.fX, e.fY);
78 #ifdef SK_DEBUG
79 if (color != e.fColor) {
80 SkDebugf("Wrong color\n\texpected: %f %f %f %f\n\tactual: %f %f %f %f",
81 e.fColor.fR,
82 e.fColor.fG,
83 e.fColor.fB,
84 e.fColor.fA,
85 color.fR,
86 color.fG,
87 color.fB,
88 color.fA);
89 }
90 #endif
91 REPORTER_ASSERT(reporter, color == e.fColor);
92 }
93 }
94
95 // 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,CtsEnforcement::kNextRelease)96 DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(RecordingSurfacesTestClear, reporter, context,
97 CtsEnforcement::kNextRelease) {
98 SkISize surfaceSize = SkISize::Make(8, 4);
99 SkISize recordingSize = SkISize::Make(4, 4);
100 SkISize replayOffset = SkISize::Make(0, 0);
101
102 auto draw = [](SkCanvas* canvas) { canvas->clear(SkColors::kRed); };
103
104 std::vector<Expectation> expectations = {{0, 0, SkColors::kRed},
105 {4, 0, SkColors::kTransparent}};
106
107 run_test(reporter, context, surfaceSize, recordingSize, replayOffset, draw, expectations);
108 }
109
110 // Tests that writePixels is translated correctly when replayed with an offset.
DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(RecordingSurfacesTestWritePixels,reporter,context,CtsEnforcement::kNextRelease)111 DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(RecordingSurfacesTestWritePixels, reporter, context,
112 CtsEnforcement::kNextRelease) {
113 SkBitmap bitmap;
114 bitmap.allocN32Pixels(4, 4, true);
115 SkCanvas bitmapCanvas(bitmap);
116 SkPaint paint;
117 paint.setColor(SkColors::kRed);
118 bitmapCanvas.drawIRect(SkIRect::MakeXYWH(0, 0, 4, 4), paint);
119
120 SkISize surfaceSize = SkISize::Make(8, 4);
121 SkISize recordingSize = SkISize::Make(4, 4);
122 SkISize replayOffset = SkISize::Make(4, 0);
123
124 auto draw = [&bitmap](SkCanvas* canvas) { canvas->writePixels(bitmap, 0, 0); };
125
126 std::vector<Expectation> expectations = {{0, 0, SkColors::kTransparent},
127 {4, 0, SkColors::kRed}};
128
129 run_test(reporter, context, surfaceSize, recordingSize, replayOffset, draw, expectations);
130 }
131
132 // Tests that the result of writePixels is cropped correctly when offscreen.
DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(RecordingSurfacesTestWritePixelsOffscreen,reporter,context,CtsEnforcement::kNextRelease)133 DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(RecordingSurfacesTestWritePixelsOffscreen, reporter, context,
134 CtsEnforcement::kNextRelease) {
135 SkBitmap bitmap;
136 bitmap.allocN32Pixels(4, 4, true);
137 SkCanvas bitmapCanvas(bitmap);
138 SkPaint paint;
139 paint.setColor(SkColors::kRed);
140 bitmapCanvas.drawIRect(SkIRect::MakeXYWH(0, 0, 4, 4), paint);
141 paint.setColor(SkColors::kGreen);
142 bitmapCanvas.drawIRect(SkIRect::MakeXYWH(2, 2, 2, 2), paint);
143
144 SkISize surfaceSize = SkISize::Make(4, 4);
145 SkISize recordingSize = SkISize::Make(4, 4);
146 SkISize replayOffset = SkISize::Make(-2, -2);
147
148 auto draw = [&bitmap](SkCanvas* canvas) { canvas->writePixels(bitmap, 0, 0); };
149
150 std::vector<Expectation> expectations = {{0, 0, SkColors::kGreen}};
151
152 run_test(reporter, context, surfaceSize, recordingSize, replayOffset, draw, expectations);
153 }
154
155 } // namespace skgpu::graphite
156