1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2016 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/core/SkBitmap.h"
9cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h"
10cb93a386Sopenharmony_ci#include "include/core/SkColor.h"
11cb93a386Sopenharmony_ci#include "include/core/SkColorSpace.h"
12cb93a386Sopenharmony_ci#include "include/core/SkImageInfo.h"
13cb93a386Sopenharmony_ci#include "include/core/SkPaint.h"
14cb93a386Sopenharmony_ci#include "include/core/SkRect.h"
15cb93a386Sopenharmony_ci#include "include/core/SkRefCnt.h"
16cb93a386Sopenharmony_ci#include "include/core/SkSurface.h"
17cb93a386Sopenharmony_ci#include "include/core/SkTypes.h"
18cb93a386Sopenharmony_ci#include "include/gpu/GrContextOptions.h"
19cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h"
20cb93a386Sopenharmony_ci#include "include/private/GrTypesPriv.h"
21cb93a386Sopenharmony_ci#include "include/private/SkColorData.h"
22cb93a386Sopenharmony_ci#include "src/core/SkAutoPixmapStorage.h"
23cb93a386Sopenharmony_ci#include "src/gpu/GrColor.h"
24cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h"
25cb93a386Sopenharmony_ci#include "src/gpu/GrImageInfo.h"
26cb93a386Sopenharmony_ci#include "src/gpu/ops/ClearOp.h"
27cb93a386Sopenharmony_ci#include "src/gpu/v1/SurfaceDrawContext_v1.h"
28cb93a386Sopenharmony_ci#include "tests/Test.h"
29cb93a386Sopenharmony_ci#include "tools/gpu/GrContextFactory.h"
30cb93a386Sopenharmony_ci
31cb93a386Sopenharmony_ci#include <cstdint>
32cb93a386Sopenharmony_ci#include <memory>
33cb93a386Sopenharmony_ci
34cb93a386Sopenharmony_ciusing SurfaceDrawContext = skgpu::v1::SurfaceDrawContext;
35cb93a386Sopenharmony_ciusing ClearOp = skgpu::v1::ClearOp;
36cb93a386Sopenharmony_ci
37cb93a386Sopenharmony_cistatic bool check_rect(GrDirectContext* dContext,
38cb93a386Sopenharmony_ci                       SurfaceDrawContext* sdc,
39cb93a386Sopenharmony_ci                       const SkIRect& rect,
40cb93a386Sopenharmony_ci                       uint32_t expectedValue,
41cb93a386Sopenharmony_ci                       uint32_t* actualValue,
42cb93a386Sopenharmony_ci                       int* failX,
43cb93a386Sopenharmony_ci                       int* failY) {
44cb93a386Sopenharmony_ci    int w = rect.width();
45cb93a386Sopenharmony_ci    int h = rect.height();
46cb93a386Sopenharmony_ci
47cb93a386Sopenharmony_ci    SkImageInfo dstInfo = SkImageInfo::Make(w, h, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
48cb93a386Sopenharmony_ci
49cb93a386Sopenharmony_ci    SkAutoPixmapStorage readback;
50cb93a386Sopenharmony_ci    readback.alloc(dstInfo);
51cb93a386Sopenharmony_ci
52cb93a386Sopenharmony_ci    readback.erase(~expectedValue);
53cb93a386Sopenharmony_ci    if (!sdc->readPixels(dContext, readback, {rect.fLeft, rect.fTop})) {
54cb93a386Sopenharmony_ci        return false;
55cb93a386Sopenharmony_ci    }
56cb93a386Sopenharmony_ci
57cb93a386Sopenharmony_ci    for (int y = 0; y < h; ++y) {
58cb93a386Sopenharmony_ci        for (int x = 0; x < w; ++x) {
59cb93a386Sopenharmony_ci            uint32_t pixel = readback.addr32()[y * w + x];
60cb93a386Sopenharmony_ci            if (pixel != expectedValue) {
61cb93a386Sopenharmony_ci                *actualValue = pixel;
62cb93a386Sopenharmony_ci                *failX = x + rect.fLeft;
63cb93a386Sopenharmony_ci                *failY = y + rect.fTop;
64cb93a386Sopenharmony_ci                return false;
65cb93a386Sopenharmony_ci            }
66cb93a386Sopenharmony_ci        }
67cb93a386Sopenharmony_ci    }
68cb93a386Sopenharmony_ci    return true;
69cb93a386Sopenharmony_ci}
70cb93a386Sopenharmony_ci
71cb93a386Sopenharmony_cistd::unique_ptr<SurfaceDrawContext> newSDC(GrRecordingContext* rContext, int w, int h) {
72cb93a386Sopenharmony_ci    return SurfaceDrawContext::Make(rContext, GrColorType::kRGBA_8888, nullptr,
73cb93a386Sopenharmony_ci                                    SkBackingFit::kExact, {w, h}, SkSurfaceProps());
74cb93a386Sopenharmony_ci}
75cb93a386Sopenharmony_ci
76cb93a386Sopenharmony_cistatic void clear_op_test(skiatest::Reporter* reporter, GrDirectContext* dContext) {
77cb93a386Sopenharmony_ci    static const int kW = 10;
78cb93a386Sopenharmony_ci    static const int kH = 10;
79cb93a386Sopenharmony_ci
80cb93a386Sopenharmony_ci    SkIRect fullRect = SkIRect::MakeWH(kW, kH);
81cb93a386Sopenharmony_ci    std::unique_ptr<SurfaceDrawContext> sdc;
82cb93a386Sopenharmony_ci
83cb93a386Sopenharmony_ci    // A rectangle that is inset by one on all sides and the 1-pixel wide rectangles that surround
84cb93a386Sopenharmony_ci    // it.
85cb93a386Sopenharmony_ci    SkIRect mid1Rect = SkIRect::MakeXYWH(1, 1, kW-2, kH-2);
86cb93a386Sopenharmony_ci    SkIRect outerLeftEdge = SkIRect::MakeXYWH(0, 0, 1, kH);
87cb93a386Sopenharmony_ci    SkIRect outerTopEdge = SkIRect::MakeXYWH(0, 0, kW, 1);
88cb93a386Sopenharmony_ci    SkIRect outerRightEdge = SkIRect::MakeXYWH(kW-1, 0, 1, kH);
89cb93a386Sopenharmony_ci    SkIRect outerBottomEdge = SkIRect::MakeXYWH(0, kH-1, kW, 1);
90cb93a386Sopenharmony_ci
91cb93a386Sopenharmony_ci    // A rectangle that is inset by two on all sides and the 1-pixel wide rectangles that surround
92cb93a386Sopenharmony_ci    // it.
93cb93a386Sopenharmony_ci    SkIRect mid2Rect = SkIRect::MakeXYWH(2, 2, kW-4, kH-4);
94cb93a386Sopenharmony_ci    SkIRect innerLeftEdge = SkIRect::MakeXYWH(1, 1, 1, kH-2);
95cb93a386Sopenharmony_ci    SkIRect innerTopEdge = SkIRect::MakeXYWH(1, 1, kW-2, 1);
96cb93a386Sopenharmony_ci    SkIRect innerRightEdge = SkIRect::MakeXYWH(kW-2, 1, 1, kH-2);
97cb93a386Sopenharmony_ci    SkIRect innerBottomEdge = SkIRect::MakeXYWH(1, kH-2, kW-2, 1);
98cb93a386Sopenharmony_ci
99cb93a386Sopenharmony_ci    uint32_t actualValue;
100cb93a386Sopenharmony_ci    int failX, failY;
101cb93a386Sopenharmony_ci
102cb93a386Sopenharmony_ci    static const GrColor kColor1 = 0xABCDEF01;
103cb93a386Sopenharmony_ci    static const GrColor kColor2 = ~kColor1;
104cb93a386Sopenharmony_ci    static const SkPMColor4f kColor1f = SkPMColor4f::FromBytes_RGBA(kColor1);
105cb93a386Sopenharmony_ci    static const SkPMColor4f kColor2f = SkPMColor4f::FromBytes_RGBA(kColor2);
106cb93a386Sopenharmony_ci
107cb93a386Sopenharmony_ci    sdc = newSDC(dContext, kW, kH);
108cb93a386Sopenharmony_ci    SkASSERT(sdc);
109cb93a386Sopenharmony_ci
110cb93a386Sopenharmony_ci    // Check a full clear
111cb93a386Sopenharmony_ci    sdc->clear(fullRect, kColor1f);
112cb93a386Sopenharmony_ci    if (!check_rect(dContext, sdc.get(), fullRect, kColor1, &actualValue, &failX, &failY)) {
113cb93a386Sopenharmony_ci        ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor1, actualValue,
114cb93a386Sopenharmony_ci               failX, failY);
115cb93a386Sopenharmony_ci    }
116cb93a386Sopenharmony_ci
117cb93a386Sopenharmony_ci    sdc = newSDC(dContext, kW, kH);
118cb93a386Sopenharmony_ci    SkASSERT(sdc);
119cb93a386Sopenharmony_ci
120cb93a386Sopenharmony_ci    // Check two full clears, same color
121cb93a386Sopenharmony_ci    sdc->clear(fullRect, kColor1f);
122cb93a386Sopenharmony_ci    sdc->clear(fullRect, kColor1f);
123cb93a386Sopenharmony_ci    if (!check_rect(dContext, sdc.get(), fullRect, kColor1, &actualValue, &failX, &failY)) {
124cb93a386Sopenharmony_ci        ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor1, actualValue,
125cb93a386Sopenharmony_ci               failX, failY);
126cb93a386Sopenharmony_ci    }
127cb93a386Sopenharmony_ci
128cb93a386Sopenharmony_ci    sdc = newSDC(dContext, kW, kH);
129cb93a386Sopenharmony_ci    SkASSERT(sdc);
130cb93a386Sopenharmony_ci
131cb93a386Sopenharmony_ci    // Check two full clears, different colors
132cb93a386Sopenharmony_ci    sdc->clear(fullRect, kColor1f);
133cb93a386Sopenharmony_ci    sdc->clear(fullRect, kColor2f);
134cb93a386Sopenharmony_ci    if (!check_rect(dContext, sdc.get(), fullRect, kColor2, &actualValue, &failX, &failY)) {
135cb93a386Sopenharmony_ci        ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor2, actualValue,
136cb93a386Sopenharmony_ci               failX, failY);
137cb93a386Sopenharmony_ci    }
138cb93a386Sopenharmony_ci
139cb93a386Sopenharmony_ci    sdc = newSDC(dContext, kW, kH);
140cb93a386Sopenharmony_ci    SkASSERT(sdc);
141cb93a386Sopenharmony_ci
142cb93a386Sopenharmony_ci    // Test a full clear followed by a same color inset clear
143cb93a386Sopenharmony_ci    sdc->clear(fullRect, kColor1f);
144cb93a386Sopenharmony_ci    sdc->clear(mid1Rect, kColor1f);
145cb93a386Sopenharmony_ci    if (!check_rect(dContext, sdc.get(), fullRect, kColor1, &actualValue, &failX, &failY)) {
146cb93a386Sopenharmony_ci        ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor1, actualValue,
147cb93a386Sopenharmony_ci               failX, failY);
148cb93a386Sopenharmony_ci    }
149cb93a386Sopenharmony_ci
150cb93a386Sopenharmony_ci    sdc = newSDC(dContext, kW, kH);
151cb93a386Sopenharmony_ci    SkASSERT(sdc);
152cb93a386Sopenharmony_ci
153cb93a386Sopenharmony_ci    // Test a inset clear followed by same color full clear
154cb93a386Sopenharmony_ci    sdc->clear(mid1Rect, kColor1f);
155cb93a386Sopenharmony_ci    sdc->clear(fullRect, kColor1f);
156cb93a386Sopenharmony_ci    if (!check_rect(dContext, sdc.get(), fullRect, kColor1, &actualValue, &failX, &failY)) {
157cb93a386Sopenharmony_ci        ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor1, actualValue,
158cb93a386Sopenharmony_ci               failX, failY);
159cb93a386Sopenharmony_ci    }
160cb93a386Sopenharmony_ci
161cb93a386Sopenharmony_ci    sdc = newSDC(dContext, kW, kH);
162cb93a386Sopenharmony_ci    SkASSERT(sdc);
163cb93a386Sopenharmony_ci
164cb93a386Sopenharmony_ci    // Test a full clear followed by a different color inset clear
165cb93a386Sopenharmony_ci    sdc->clear(fullRect, kColor1f);
166cb93a386Sopenharmony_ci    sdc->clear(mid1Rect, kColor2f);
167cb93a386Sopenharmony_ci    if (!check_rect(dContext, sdc.get(), mid1Rect, kColor2, &actualValue, &failX, &failY)) {
168cb93a386Sopenharmony_ci        ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor2, actualValue,
169cb93a386Sopenharmony_ci               failX, failY);
170cb93a386Sopenharmony_ci    }
171cb93a386Sopenharmony_ci    if (!check_rect(dContext, sdc.get(), outerLeftEdge, kColor1, &actualValue, &failX, &failY) ||
172cb93a386Sopenharmony_ci        !check_rect(dContext, sdc.get(), outerTopEdge, kColor1, &actualValue, &failX, &failY) ||
173cb93a386Sopenharmony_ci        !check_rect(dContext, sdc.get(), outerRightEdge, kColor1, &actualValue, &failX, &failY) ||
174cb93a386Sopenharmony_ci        !check_rect(dContext, sdc.get(), outerBottomEdge, kColor1, &actualValue, &failX, &failY)) {
175cb93a386Sopenharmony_ci        ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor1, actualValue,
176cb93a386Sopenharmony_ci               failX, failY);
177cb93a386Sopenharmony_ci    }
178cb93a386Sopenharmony_ci
179cb93a386Sopenharmony_ci    sdc = newSDC(dContext, kW, kH);
180cb93a386Sopenharmony_ci    SkASSERT(sdc);
181cb93a386Sopenharmony_ci
182cb93a386Sopenharmony_ci    // Test a inset clear followed by a different full clear
183cb93a386Sopenharmony_ci    sdc->clear(mid1Rect, kColor2f);
184cb93a386Sopenharmony_ci    sdc->clear(fullRect, kColor1f);
185cb93a386Sopenharmony_ci    if (!check_rect(dContext, sdc.get(), fullRect, kColor1, &actualValue, &failX, &failY)) {
186cb93a386Sopenharmony_ci        ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor1, actualValue,
187cb93a386Sopenharmony_ci               failX, failY);
188cb93a386Sopenharmony_ci    }
189cb93a386Sopenharmony_ci
190cb93a386Sopenharmony_ci    sdc = newSDC(dContext, kW, kH);
191cb93a386Sopenharmony_ci    SkASSERT(sdc);
192cb93a386Sopenharmony_ci
193cb93a386Sopenharmony_ci    // Check three nested clears from largest to smallest where outermost and innermost are same
194cb93a386Sopenharmony_ci    // color.
195cb93a386Sopenharmony_ci    sdc->clear(fullRect, kColor1f);
196cb93a386Sopenharmony_ci    sdc->clear(mid1Rect, kColor2f);
197cb93a386Sopenharmony_ci    sdc->clear(mid2Rect, kColor1f);
198cb93a386Sopenharmony_ci    if (!check_rect(dContext, sdc.get(), mid2Rect, kColor1, &actualValue, &failX, &failY)) {
199cb93a386Sopenharmony_ci        ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor1, actualValue,
200cb93a386Sopenharmony_ci               failX, failY);
201cb93a386Sopenharmony_ci    }
202cb93a386Sopenharmony_ci    if (!check_rect(dContext, sdc.get(), innerLeftEdge, kColor2, &actualValue, &failX, &failY) ||
203cb93a386Sopenharmony_ci        !check_rect(dContext, sdc.get(), innerTopEdge, kColor2, &actualValue, &failX, &failY) ||
204cb93a386Sopenharmony_ci        !check_rect(dContext, sdc.get(), innerRightEdge, kColor2, &actualValue, &failX, &failY) ||
205cb93a386Sopenharmony_ci        !check_rect(dContext, sdc.get(), innerBottomEdge, kColor2, &actualValue, &failX, &failY)) {
206cb93a386Sopenharmony_ci        ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor2, actualValue,
207cb93a386Sopenharmony_ci               failX, failY);
208cb93a386Sopenharmony_ci    }
209cb93a386Sopenharmony_ci    if (!check_rect(dContext, sdc.get(), outerLeftEdge, kColor1, &actualValue, &failX, &failY) ||
210cb93a386Sopenharmony_ci        !check_rect(dContext, sdc.get(), outerTopEdge, kColor1, &actualValue, &failX, &failY) ||
211cb93a386Sopenharmony_ci        !check_rect(dContext, sdc.get(), outerRightEdge, kColor1, &actualValue, &failX, &failY) ||
212cb93a386Sopenharmony_ci        !check_rect(dContext, sdc.get(), outerBottomEdge, kColor1, &actualValue, &failX, &failY)) {
213cb93a386Sopenharmony_ci        ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor1, actualValue,
214cb93a386Sopenharmony_ci               failX, failY);
215cb93a386Sopenharmony_ci    }
216cb93a386Sopenharmony_ci
217cb93a386Sopenharmony_ci    sdc = newSDC(dContext, kW, kH);
218cb93a386Sopenharmony_ci    SkASSERT(sdc);
219cb93a386Sopenharmony_ci
220cb93a386Sopenharmony_ci    // Swap the order of the second two clears in the above test.
221cb93a386Sopenharmony_ci    sdc->clear(fullRect, kColor1f);
222cb93a386Sopenharmony_ci    sdc->clear(mid2Rect, kColor1f);
223cb93a386Sopenharmony_ci    sdc->clear(mid1Rect, kColor2f);
224cb93a386Sopenharmony_ci    if (!check_rect(dContext, sdc.get(), mid1Rect, kColor2, &actualValue, &failX, &failY)) {
225cb93a386Sopenharmony_ci        ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor2, actualValue,
226cb93a386Sopenharmony_ci               failX, failY);
227cb93a386Sopenharmony_ci    }
228cb93a386Sopenharmony_ci    if (!check_rect(dContext, sdc.get(), outerLeftEdge, kColor1, &actualValue, &failX, &failY) ||
229cb93a386Sopenharmony_ci        !check_rect(dContext, sdc.get(), outerTopEdge, kColor1, &actualValue, &failX, &failY) ||
230cb93a386Sopenharmony_ci        !check_rect(dContext, sdc.get(), outerRightEdge, kColor1, &actualValue, &failX, &failY) ||
231cb93a386Sopenharmony_ci        !check_rect(dContext, sdc.get(), outerBottomEdge, kColor1, &actualValue, &failX, &failY)) {
232cb93a386Sopenharmony_ci        ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor1, actualValue,
233cb93a386Sopenharmony_ci               failX, failY);
234cb93a386Sopenharmony_ci    }
235cb93a386Sopenharmony_ci
236cb93a386Sopenharmony_ci    // Clear calls need to remain ClearOps for the following combining-tests to work as expected
237cb93a386Sopenharmony_ci    if (!dContext->priv().caps()->performColorClearsAsDraws() &&
238cb93a386Sopenharmony_ci        !dContext->priv().caps()->performStencilClearsAsDraws() &&
239cb93a386Sopenharmony_ci        !dContext->priv().caps()->performPartialClearsAsDraws()) {
240cb93a386Sopenharmony_ci        static constexpr SkIRect kScissorRect = SkIRect::MakeXYWH(1, 1, kW-1, kH-1);
241cb93a386Sopenharmony_ci
242cb93a386Sopenharmony_ci        // Try combining a pure-color clear w/ a combined stencil & color clear
243cb93a386Sopenharmony_ci        // (re skbug.com/10963)
244cb93a386Sopenharmony_ci        {
245cb93a386Sopenharmony_ci            sdc = newSDC(dContext, kW, kH);
246cb93a386Sopenharmony_ci            SkASSERT(sdc);
247cb93a386Sopenharmony_ci
248cb93a386Sopenharmony_ci            sdc->clearStencilClip(kScissorRect, true);
249cb93a386Sopenharmony_ci            // This color clear can combine w/ the preceding stencil clear
250cb93a386Sopenharmony_ci            sdc->clear(kScissorRect, SK_PMColor4fWHITE);
251cb93a386Sopenharmony_ci
252cb93a386Sopenharmony_ci            // This should combine w/ the prior combined clear and overwrite the color
253cb93a386Sopenharmony_ci            sdc->clear(kScissorRect, SK_PMColor4fBLACK);
254cb93a386Sopenharmony_ci
255cb93a386Sopenharmony_ci            auto opsTask = sdc->getOpsTask();
256cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, opsTask->numOpChains() == 1);
257cb93a386Sopenharmony_ci
258cb93a386Sopenharmony_ci            const ClearOp& clearOp = opsTask->getChain(0)->cast<ClearOp>();
259cb93a386Sopenharmony_ci
260cb93a386Sopenharmony_ci            constexpr std::array<float, 4> kExpected { 0, 0, 0, 1 };
261cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, clearOp.color() == kExpected);
262cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, clearOp.stencilInsideMask());
263cb93a386Sopenharmony_ci
264cb93a386Sopenharmony_ci            dContext->flushAndSubmit();
265cb93a386Sopenharmony_ci        }
266cb93a386Sopenharmony_ci
267cb93a386Sopenharmony_ci        // Try combining a pure-stencil clear w/ a combined stencil & color clear
268cb93a386Sopenharmony_ci        // (re skbug.com/10963)
269cb93a386Sopenharmony_ci        {
270cb93a386Sopenharmony_ci            sdc = newSDC(dContext, kW, kH);
271cb93a386Sopenharmony_ci            SkASSERT(sdc);
272cb93a386Sopenharmony_ci
273cb93a386Sopenharmony_ci            sdc->clearStencilClip(kScissorRect, true);
274cb93a386Sopenharmony_ci            // This color clear can combine w/ the preceding stencil clear
275cb93a386Sopenharmony_ci            sdc->clear(kScissorRect, SK_PMColor4fWHITE);
276cb93a386Sopenharmony_ci
277cb93a386Sopenharmony_ci            // This should combine w/ the prior combined clear and overwrite the 'insideStencilMask'
278cb93a386Sopenharmony_ci            // field
279cb93a386Sopenharmony_ci            sdc->clearStencilClip(kScissorRect, false);
280cb93a386Sopenharmony_ci
281cb93a386Sopenharmony_ci            auto opsTask = sdc->getOpsTask();
282cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, opsTask->numOpChains() == 1);
283cb93a386Sopenharmony_ci
284cb93a386Sopenharmony_ci            const ClearOp& clearOp = opsTask->getChain(0)->cast<ClearOp>();
285cb93a386Sopenharmony_ci
286cb93a386Sopenharmony_ci            constexpr std::array<float, 4> kExpected { 1, 1, 1, 1 };
287cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, clearOp.color() == kExpected);
288cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, !clearOp.stencilInsideMask());
289cb93a386Sopenharmony_ci
290cb93a386Sopenharmony_ci            dContext->flushAndSubmit();
291cb93a386Sopenharmony_ci        }
292cb93a386Sopenharmony_ci    }
293cb93a386Sopenharmony_ci}
294cb93a386Sopenharmony_ci
295cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(ClearOp, reporter, ctxInfo) {
296cb93a386Sopenharmony_ci    // Regular clear
297cb93a386Sopenharmony_ci    clear_op_test(reporter, ctxInfo.directContext());
298cb93a386Sopenharmony_ci
299cb93a386Sopenharmony_ci    // Force drawing for clears
300cb93a386Sopenharmony_ci    GrContextOptions options(ctxInfo.options());
301cb93a386Sopenharmony_ci    options.fUseDrawInsteadOfClear = GrContextOptions::Enable::kYes;
302cb93a386Sopenharmony_ci    sk_gpu_test::GrContextFactory workaroundFactory(options);
303cb93a386Sopenharmony_ci    clear_op_test(reporter, workaroundFactory.get(ctxInfo.type()));
304cb93a386Sopenharmony_ci}
305cb93a386Sopenharmony_ci
306cb93a386Sopenharmony_civoid fullscreen_clear_with_layer_test(skiatest::Reporter* reporter, GrRecordingContext* rContext) {
307cb93a386Sopenharmony_ci    const SkImageInfo ii = SkImageInfo::Make(400, 77, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
308cb93a386Sopenharmony_ci
309cb93a386Sopenharmony_ci    sk_sp<SkSurface> surf = SkSurface::MakeRenderTarget(rContext, SkBudgeted::kYes, ii);
310cb93a386Sopenharmony_ci    SkCanvas* canvas = surf->getCanvas();
311cb93a386Sopenharmony_ci
312cb93a386Sopenharmony_ci    SkPaint paints[2];
313cb93a386Sopenharmony_ci    paints[0].setColor(SK_ColorGREEN);
314cb93a386Sopenharmony_ci    paints[1].setColor(SK_ColorGRAY);
315cb93a386Sopenharmony_ci
316cb93a386Sopenharmony_ci    static const int kLeftX = 158;
317cb93a386Sopenharmony_ci    static const int kMidX = 258;
318cb93a386Sopenharmony_ci    static const int kRightX = 383;
319cb93a386Sopenharmony_ci    static const int kTopY = 26;
320cb93a386Sopenharmony_ci    static const int kBotY = 51;
321cb93a386Sopenharmony_ci
322cb93a386Sopenharmony_ci    const SkRect rects[2] = {
323cb93a386Sopenharmony_ci        { kLeftX, kTopY, kMidX, kBotY },
324cb93a386Sopenharmony_ci        { kMidX, kTopY, kRightX, kBotY },
325cb93a386Sopenharmony_ci    };
326cb93a386Sopenharmony_ci
327cb93a386Sopenharmony_ci    for (int i = 0; i < 2; ++i) {
328cb93a386Sopenharmony_ci        // the bounds parameter is required to cause a full screen clear
329cb93a386Sopenharmony_ci        canvas->saveLayer(&rects[i], nullptr);
330cb93a386Sopenharmony_ci            canvas->drawRect(rects[i], paints[i]);
331cb93a386Sopenharmony_ci        canvas->restore();
332cb93a386Sopenharmony_ci    }
333cb93a386Sopenharmony_ci
334cb93a386Sopenharmony_ci    SkBitmap bm;
335cb93a386Sopenharmony_ci    bm.allocPixels(ii, 0);
336cb93a386Sopenharmony_ci
337cb93a386Sopenharmony_ci    SkAssertResult(surf->readPixels(bm, 0, 0));
338cb93a386Sopenharmony_ci
339cb93a386Sopenharmony_ci    bool isCorrect = true;
340cb93a386Sopenharmony_ci    for (int y = kTopY; isCorrect && y < kBotY; ++y) {
341cb93a386Sopenharmony_ci        const uint32_t* sl = bm.getAddr32(0, y);
342cb93a386Sopenharmony_ci
343cb93a386Sopenharmony_ci        for (int x = kLeftX; x < kMidX; ++x) {
344cb93a386Sopenharmony_ci            if (SK_ColorGREEN != sl[x]) {
345cb93a386Sopenharmony_ci                isCorrect = false;
346cb93a386Sopenharmony_ci                break;
347cb93a386Sopenharmony_ci            }
348cb93a386Sopenharmony_ci        }
349cb93a386Sopenharmony_ci
350cb93a386Sopenharmony_ci        for (int x = kMidX; x < kRightX; ++x) {
351cb93a386Sopenharmony_ci            if (SK_ColorGRAY != sl[x]) {
352cb93a386Sopenharmony_ci                isCorrect = false;
353cb93a386Sopenharmony_ci                break;
354cb93a386Sopenharmony_ci            }
355cb93a386Sopenharmony_ci        }
356cb93a386Sopenharmony_ci    }
357cb93a386Sopenharmony_ci
358cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, isCorrect);
359cb93a386Sopenharmony_ci}
360cb93a386Sopenharmony_ci// From crbug.com/768134
361cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(FullScreenClearWithLayers, reporter, ctxInfo) {
362cb93a386Sopenharmony_ci    // Regular clear
363cb93a386Sopenharmony_ci    fullscreen_clear_with_layer_test(reporter, ctxInfo.directContext());
364cb93a386Sopenharmony_ci
365cb93a386Sopenharmony_ci    // Use draws for clears
366cb93a386Sopenharmony_ci    GrContextOptions options(ctxInfo.options());
367cb93a386Sopenharmony_ci    options.fUseDrawInsteadOfClear = GrContextOptions::Enable::kYes;
368cb93a386Sopenharmony_ci    sk_gpu_test::GrContextFactory workaroundFactory(options);
369cb93a386Sopenharmony_ci    fullscreen_clear_with_layer_test(reporter, workaroundFactory.get(ctxInfo.type()));
370cb93a386Sopenharmony_ci}
371