Flutter Engine
The Flutter Engine
WrappedSurfaceCopyOnWriteTest.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2021 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
15#include "include/core/SkRect.h"
22#include "include/gpu/GrTypes.h"
42#include "tests/Test.h"
43#include "tests/TestUtils.h"
46
47#include <functional>
48#include <memory>
49
50struct GrContextOptions;
51
52DEF_GANESH_TEST_FOR_ALL_CONTEXTS(WrappedSurfaceCopyOnWrite,
54 ctxInfo,
56 using namespace skgpu;
57
58 GrDirectContext* dContext = ctxInfo.directContext();
59
60 Protected isProtected = Protected(dContext->priv().caps()->supportsProtectedContent());
61
62 auto makeDirectBackendSurface = [&]() {
65 info,
67 /* sampleCnt= */ 1,
69 isProtected);
70 };
71
72 auto imageProxyID = [&](const sk_sp<SkImage>& img) {
73 return sk_gpu_test::GetTextureImageProxy(img.get(), dContext)->uniqueID();
74 };
75
76 auto surfaceProxyID = [&](const sk_sp<SkSurface>& surf) {
78 return rtp->uniqueID();
79 };
80
81 sk_sp<SkSurface> surf = makeDirectBackendSurface();
82 surf->getCanvas()->clear(SkColor4f{1, 0, 0, 1});
84 // Initially they share
85 REPORTER_ASSERT(reporter, surfaceProxyID(surf) == imageProxyID(img));
86 // Using the image on the direct context shouldn't affect sharing.
87 sk_sp<SkSurface> surf2 = makeDirectBackendSurface();
88 surf2->getCanvas()->drawImage(img, 0, 0);
89 REPORTER_ASSERT(reporter, surfaceProxyID(surf) == imageProxyID(img));
90 // Modifying the original surface should trigger using the copy proxy.
91 surf->getCanvas()->clear({0, 0, 1, 1});
92 REPORTER_ASSERT(reporter, surfaceProxyID(surf) != imageProxyID(img));
93 // Image caching on surface should mean another snapshot gives us the same image.
94 GrSurfaceProxy::UniqueID imageID = imageProxyID(img);
95 img = surf->makeImageSnapshot();
96 REPORTER_ASSERT(reporter, imageProxyID(img) != imageID);
97
98 GrSurfaceCharacterization characterization;
99 REPORTER_ASSERT(reporter, surf->characterize(&characterization));
100 GrDeferredDisplayListRecorder recorder(characterization);
101
102 // Using an image from a direct context on a recording context should trigger using the copy.
103 surf = makeDirectBackendSurface();
104 img = surf->makeImageSnapshot();
105 REPORTER_ASSERT(reporter, surfaceProxyID(surf) == imageProxyID(img));
106 recorder.getCanvas()->drawImage(img, 0, 0);
107 REPORTER_ASSERT(reporter, surfaceProxyID(surf) != imageProxyID(img));
108
109 // Same as above but if the surface goes out of scope first we keep using the original
110 surf = makeDirectBackendSurface();
111 img = surf->makeImageSnapshot();
112 GrSurfaceProxy::UniqueID surfID = surfaceProxyID(surf);
113 REPORTER_ASSERT(reporter, surfaceProxyID(surf) == imageProxyID(img));
114 surf.reset();
115 recorder.getCanvas()->drawImage(img, 0, 0);
116 REPORTER_ASSERT(reporter, surfID == imageProxyID(img));
117}
118
119// Make sure GrCopyRenderTasks's skip actually skips the copy.
121 reporter,
122 ctxInfo,
124 GrDirectContext* dContext = ctxInfo.directContext();
125
128 /*color space*/ nullptr,
129 10, 10);
130
131 auto dstSC = CreateSurfaceContext(dContext,
132 info,
136 dstSC->asFillContext()->clear(SkPMColor4f{1, 0, 0, 1});
137
138 auto srcSC = CreateSurfaceContext(dContext,
139 info,
143 srcSC->asFillContext()->clear(SkPMColor4f{0, 0, 1, 1});
144
146 dContext->priv().drawingManager()->newCopyRenderTask(dstSC->asSurfaceProxyRef(),
147 SkIRect::MakeWH(10, 10),
148 srcSC->asSurfaceProxyRef(),
149 SkIRect::MakeWH(10, 10),
152
153 if (!task) {
154 ERRORF(reporter, "Couldn't make a copy task.");
155 return;
156 }
157
158 task->makeSkippable();
159
160 SkAutoPixmapStorage pixels;
162 dstSC->readPixels(dContext, pixels, {0, 0});
163 float kTol[4] = {};
164 std::function<ComparePixmapsErrorReporter> errorReporter(
165 [&](int x, int y, const float diffs[4]) {
166 ERRORF(reporter, "Expected {1, 0, 0, 1}. diff {%f, %f, %f, %f}",
167 diffs[0], diffs[1], diffs[2], diffs[3]);
168 });
169 CheckSolidPixels(SkColor4f{1, 0, 0, 1}, pixels, kTol, errorReporter);
170}
171
172#if defined(SK_GANESH)
173
174// Make sure OpsTask are skippable
176 GrDirectContext* dContext = ctxInfo.directContext();
177
178 GrImageInfo ii(GrColorType::kRGBA_8888, kPremul_SkAlphaType, /*color space*/ nullptr, 10, 10);
179
180 auto dst = dContext->priv().makeSFC(ii, /*label=*/{}, SkBackingFit::kExact);
181 dst->clear(SkPMColor4f{1, 0, 0, 1});
182 dContext->flush();
183
184 dst->clear(SkPMColor4f{0, 0, 1, 1});
185 sk_sp<GrRenderTask> task = dst->refRenderTask();
186
187 // GrDrawingManager maintains an "active ops task" and doesn't like having it closed behind
188 // its back. temp exists just to replace dst's ops task as the active one.
189 auto temp = dContext->priv().makeSFC(ii, /*label=*/{}, SkBackingFit::kExact);
190 temp->clear(SkPMColor4f{0, 0, 0, 0});
191
192 GrSurfaceProxyView readView = dst->readSurfaceView();
193 task->makeSkippable();
194
195 SkAutoPixmapStorage pixels;
197 dst->readPixels(dContext, pixels, {0, 0});
198 float kTol[4] = {};
199 std::function<ComparePixmapsErrorReporter> errorReporter(
200 [&](int x, int y, const float diffs[4]) {
201 ERRORF(reporter, "Expected {1, 0, 0, 1}. diff {%f, %f, %f, %f}",
202 diffs[0], diffs[1], diffs[2], diffs[3]);
203 });
204 CheckSolidPixels(SkColor4f{1, 0, 0, 1}, pixels, kTol, errorReporter);
205}
206#endif // defined(SK_GANESH)
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
reporter
Definition: FontMgrTest.cpp:39
@ kBottomLeft_GrSurfaceOrigin
Definition: GrTypes.h:149
@ kTopLeft_GrSurfaceOrigin
Definition: GrTypes.h:148
skgpu::Protected Protected
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition: SkAlphaType.h:29
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition: SkColorType.h:24
std::unique_ptr< skgpu::ganesh::SurfaceContext > CreateSurfaceContext(GrRecordingContext *rContext, const GrImageInfo &info, SkBackingFit fit, GrSurfaceOrigin origin, GrRenderable renderable, int sampleCount, skgpu::Mipmapped mipmapped, GrProtected isProtected, skgpu::Budgeted budgeted)
Definition: TestUtils.cpp:242
bool CheckSolidPixels(const SkColor4f &col, const SkPixmap &pixmap, const float tolRGBA[4], std::function< ComparePixmapsErrorReporter > &error)
Definition: TestUtils.cpp:191
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
#define ERRORF(r,...)
Definition: Test.h:293
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SkipCopyTaskTest, reporter, ctxInfo, CtsEnforcement::kNever)
DEF_GANESH_TEST_FOR_ALL_CONTEXTS(WrappedSurfaceCopyOnWrite, reporter, ctxInfo, CtsEnforcement::kApiLevel_T)
const GrCaps * caps() const
bool supportsProtectedContent() const
Definition: GrCaps.h:422
GrSemaphoresSubmitted flush(const GrFlushInfo &info)
GrDirectContextPriv priv()
sk_sp< GrRenderTask > newCopyRenderTask(sk_sp< GrSurfaceProxy > dst, SkIRect dstRect, const sk_sp< GrSurfaceProxy > &src, SkIRect srcRect, GrSamplerState::Filter filter, GrSurfaceOrigin)
GrDrawingManager * drawingManager()
std::unique_ptr< skgpu::ganesh::SurfaceFillContext > makeSFC(GrImageInfo, std::string_view label, SkBackingFit=SkBackingFit::kExact, int sampleCount=1, skgpu::Mipmapped=skgpu::Mipmapped::kNo, skgpu::Protected=skgpu::Protected::kNo, GrSurfaceOrigin=kTopLeft_GrSurfaceOrigin, skgpu::Budgeted=skgpu::Budgeted::kYes)
void makeSkippable()
UniqueID uniqueID() const
void alloc(const SkImageInfo &)
void clear(SkColor color)
Definition: SkCanvas.h:1199
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition: SkCanvas.h:1528
SkCanvas * getCanvas()
Definition: SkSurface.cpp:82
bool characterize(GrSurfaceCharacterization *characterization) const
Definition: SkSurface.cpp:239
sk_sp< SkImage > makeImageSnapshot()
Definition: SkSurface.cpp:90
void reset(T *ptr=nullptr)
Definition: SkRefCnt.h:310
double y
double x
dst
Definition: cp.py:12
GrTextureProxy * GetTextureImageProxy(SkImage *image, GrRecordingContext *rContext)
Definition: ProxyUtils.cpp:32
sk_sp< SkSurface > MakeBackendTextureSurface(GrDirectContext *dContext, const SkImageInfo &ii, GrSurfaceOrigin origin, int sampleCnt, skgpu::Mipmapped mipmapped, GrProtected isProtected, const SkSurfaceProps *props)
GrRenderTargetProxy * TopDeviceTargetProxy(const SkCanvas *canvas)
Definition: GrCanvas.cpp:34
Definition: GpuTools.h:21
Protected
Definition: GpuTypes.h:61
static constexpr SkIRect MakeWH(int32_t w, int32_t h)
Definition: SkRect.h:56
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)