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/SkImage.h"
11cb93a386Sopenharmony_ci#include "include/core/SkPixmap.h"
12cb93a386Sopenharmony_ci#include "include/core/SkSurface.h"
13cb93a386Sopenharmony_ci#include "include/gpu/GrBackendSurface.h"
14cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h"
15cb93a386Sopenharmony_ci#include "src/core/SkAutoPixmapStorage.h"
16cb93a386Sopenharmony_ci#include "src/core/SkSpecialImage.h"
17cb93a386Sopenharmony_ci#include "src/core/SkSpecialSurface.h"
18cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h"
19cb93a386Sopenharmony_ci#include "src/gpu/GrProxyProvider.h"
20cb93a386Sopenharmony_ci#include "src/gpu/GrSurfaceProxy.h"
21cb93a386Sopenharmony_ci#include "src/gpu/GrTextureProxy.h"
22cb93a386Sopenharmony_ci#include "src/gpu/SkGr.h"
23cb93a386Sopenharmony_ci#include "tests/Test.h"
24cb93a386Sopenharmony_ci
25cb93a386Sopenharmony_ci// This test creates backing resources exactly sized to [kFullSize x kFullSize].
26cb93a386Sopenharmony_ci// It then wraps them in an SkSpecialImage with only the center (red) region being active.
27cb93a386Sopenharmony_ci// It then draws the SkSpecialImage to a full sized (all blue) canvas and checks that none
28cb93a386Sopenharmony_ci// of the inactive (green) region leaked out.
29cb93a386Sopenharmony_ci
30cb93a386Sopenharmony_cistatic const int kSmallerSize = 10;
31cb93a386Sopenharmony_cistatic const int kPad = 3;
32cb93a386Sopenharmony_cistatic const int kFullSize = kSmallerSize + 2 * kPad;
33cb93a386Sopenharmony_ci
34cb93a386Sopenharmony_ci// Create a bitmap with red in the center and green around it
35cb93a386Sopenharmony_cistatic SkBitmap create_bm() {
36cb93a386Sopenharmony_ci    SkImageInfo ii = SkImageInfo::Make(kFullSize, kFullSize, kRGBA_8888_SkColorType,
37cb93a386Sopenharmony_ci                                       kPremul_SkAlphaType);
38cb93a386Sopenharmony_ci
39cb93a386Sopenharmony_ci    SkBitmap bm;
40cb93a386Sopenharmony_ci    bm.allocPixels(ii);
41cb93a386Sopenharmony_ci
42cb93a386Sopenharmony_ci    SkCanvas temp(bm);
43cb93a386Sopenharmony_ci
44cb93a386Sopenharmony_ci    temp.clear(SK_ColorGREEN);
45cb93a386Sopenharmony_ci    SkPaint p;
46cb93a386Sopenharmony_ci    p.setColor(SK_ColorRED);
47cb93a386Sopenharmony_ci    p.setAntiAlias(false);
48cb93a386Sopenharmony_ci
49cb93a386Sopenharmony_ci    temp.drawRect(SkRect::MakeXYWH(SkIntToScalar(kPad), SkIntToScalar(kPad),
50cb93a386Sopenharmony_ci                                   SkIntToScalar(kSmallerSize), SkIntToScalar(kSmallerSize)),
51cb93a386Sopenharmony_ci                  p);
52cb93a386Sopenharmony_ci
53cb93a386Sopenharmony_ci    bm.setImmutable();
54cb93a386Sopenharmony_ci    return bm;
55cb93a386Sopenharmony_ci}
56cb93a386Sopenharmony_ci
57cb93a386Sopenharmony_ci// Basic test of the SkSpecialImage public API (e.g., peekTexture, peekPixels & draw)
58cb93a386Sopenharmony_cistatic void test_image(const sk_sp<SkSpecialImage>& img, skiatest::Reporter* reporter,
59cb93a386Sopenharmony_ci                       GrRecordingContext* rContext, bool isGPUBacked) {
60cb93a386Sopenharmony_ci    const SkIRect subset = img->subset();
61cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, kPad == subset.left());
62cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, kPad == subset.top());
63cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, kSmallerSize == subset.width());
64cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, kSmallerSize == subset.height());
65cb93a386Sopenharmony_ci
66cb93a386Sopenharmony_ci    //--------------
67cb93a386Sopenharmony_ci    // Test that isTextureBacked reports the correct backing type
68cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, isGPUBacked == img->isTextureBacked());
69cb93a386Sopenharmony_ci
70cb93a386Sopenharmony_ci    //--------------
71cb93a386Sopenharmony_ci    // Test view - as long as there is a context this should succeed
72cb93a386Sopenharmony_ci    if (rContext) {
73cb93a386Sopenharmony_ci        GrSurfaceProxyView view = img->view(rContext);
74cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, view.asTextureProxy());
75cb93a386Sopenharmony_ci    }
76cb93a386Sopenharmony_ci
77cb93a386Sopenharmony_ci    //--------------
78cb93a386Sopenharmony_ci    // Test getROPixels - this only works for raster-backed special images
79cb93a386Sopenharmony_ci    if (!img->isTextureBacked()) {
80cb93a386Sopenharmony_ci        SkBitmap bitmap;
81cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, img->getROPixels(&bitmap));
82cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, kSmallerSize == bitmap.width());
83cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, kSmallerSize == bitmap.height());
84cb93a386Sopenharmony_ci    }
85cb93a386Sopenharmony_ci
86cb93a386Sopenharmony_ci    //--------------
87cb93a386Sopenharmony_ci    // Test that draw restricts itself to the subset
88cb93a386Sopenharmony_ci    sk_sp<SkSpecialSurface> surf(img->makeSurface(kN32_SkColorType, img->getColorSpace(),
89cb93a386Sopenharmony_ci                                                  SkISize::Make(kFullSize, kFullSize),
90cb93a386Sopenharmony_ci                                                  kPremul_SkAlphaType, SkSurfaceProps()));
91cb93a386Sopenharmony_ci
92cb93a386Sopenharmony_ci    SkCanvas* canvas = surf->getCanvas();
93cb93a386Sopenharmony_ci
94cb93a386Sopenharmony_ci    canvas->clear(SK_ColorBLUE);
95cb93a386Sopenharmony_ci    img->draw(canvas, SkIntToScalar(kPad), SkIntToScalar(kPad));
96cb93a386Sopenharmony_ci
97cb93a386Sopenharmony_ci    SkBitmap bm;
98cb93a386Sopenharmony_ci    bm.allocN32Pixels(kFullSize, kFullSize, false);
99cb93a386Sopenharmony_ci
100cb93a386Sopenharmony_ci    bool result = canvas->readPixels(bm.info(), bm.getPixels(), bm.rowBytes(), 0, 0);
101cb93a386Sopenharmony_ci    SkASSERT_RELEASE(result);
102cb93a386Sopenharmony_ci
103cb93a386Sopenharmony_ci    // Only the center (red) portion should've been drawn into the canvas
104cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, SK_ColorBLUE == bm.getColor(kPad-1, kPad-1));
105cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, SK_ColorRED  == bm.getColor(kPad, kPad));
106cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, SK_ColorRED  == bm.getColor(kSmallerSize+kPad-1,
107cb93a386Sopenharmony_ci                                                          kSmallerSize+kPad-1));
108cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, SK_ColorBLUE == bm.getColor(kSmallerSize+kPad,
109cb93a386Sopenharmony_ci                                                          kSmallerSize+kPad));
110cb93a386Sopenharmony_ci
111cb93a386Sopenharmony_ci    //--------------
112cb93a386Sopenharmony_ci    // Test that asImage & makeTightSurface return appropriately sized objects
113cb93a386Sopenharmony_ci    // of the correct backing type
114cb93a386Sopenharmony_ci    SkIRect newSubset = SkIRect::MakeWH(subset.width(), subset.height());
115cb93a386Sopenharmony_ci    {
116cb93a386Sopenharmony_ci        sk_sp<SkImage> tightImg(img->asImage(&newSubset));
117cb93a386Sopenharmony_ci
118cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, tightImg->width() == subset.width());
119cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, tightImg->height() == subset.height());
120cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, isGPUBacked == tightImg->isTextureBacked());
121cb93a386Sopenharmony_ci        SkPixmap tmpPixmap;
122cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, isGPUBacked != !!tightImg->peekPixels(&tmpPixmap));
123cb93a386Sopenharmony_ci    }
124cb93a386Sopenharmony_ci    {
125cb93a386Sopenharmony_ci        sk_sp<SkSurface> tightSurf(img->makeTightSurface(kN32_SkColorType, img->getColorSpace(),
126cb93a386Sopenharmony_ci                                                         subset.size()));
127cb93a386Sopenharmony_ci
128cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, tightSurf->width() == subset.width());
129cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, tightSurf->height() == subset.height());
130cb93a386Sopenharmony_ci        GrBackendTexture backendTex = tightSurf->getBackendTexture(
131cb93a386Sopenharmony_ci                                                    SkSurface::kDiscardWrite_BackendHandleAccess);
132cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, isGPUBacked == backendTex.isValid());
133cb93a386Sopenharmony_ci        SkPixmap tmpPixmap;
134cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, isGPUBacked != !!tightSurf->peekPixels(&tmpPixmap));
135cb93a386Sopenharmony_ci    }
136cb93a386Sopenharmony_ci}
137cb93a386Sopenharmony_ci
138cb93a386Sopenharmony_ciDEF_TEST(SpecialImage_Raster, reporter) {
139cb93a386Sopenharmony_ci    SkBitmap bm = create_bm();
140cb93a386Sopenharmony_ci
141cb93a386Sopenharmony_ci    sk_sp<SkSpecialImage> fullSImage(SkSpecialImage::MakeFromRaster(
142cb93a386Sopenharmony_ci                                                            SkIRect::MakeWH(kFullSize, kFullSize),
143cb93a386Sopenharmony_ci                                                            bm, SkSurfaceProps()));
144cb93a386Sopenharmony_ci
145cb93a386Sopenharmony_ci    const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
146cb93a386Sopenharmony_ci
147cb93a386Sopenharmony_ci    {
148cb93a386Sopenharmony_ci        sk_sp<SkSpecialImage> subSImg1(SkSpecialImage::MakeFromRaster(subset, bm,
149cb93a386Sopenharmony_ci                                                                      SkSurfaceProps()));
150cb93a386Sopenharmony_ci        test_image(subSImg1, reporter, nullptr, false);
151cb93a386Sopenharmony_ci    }
152cb93a386Sopenharmony_ci
153cb93a386Sopenharmony_ci    {
154cb93a386Sopenharmony_ci        sk_sp<SkSpecialImage> subSImg2(fullSImage->makeSubset(subset));
155cb93a386Sopenharmony_ci        test_image(subSImg2, reporter, nullptr, false);
156cb93a386Sopenharmony_ci    }
157cb93a386Sopenharmony_ci}
158cb93a386Sopenharmony_ci
159cb93a386Sopenharmony_cistatic void test_specialimage_image(skiatest::Reporter* reporter) {
160cb93a386Sopenharmony_ci    SkBitmap bm = create_bm();
161cb93a386Sopenharmony_ci
162cb93a386Sopenharmony_ci    sk_sp<SkImage> fullImage(bm.asImage());
163cb93a386Sopenharmony_ci
164cb93a386Sopenharmony_ci    sk_sp<SkSpecialImage> fullSImage(SkSpecialImage::MakeFromImage(
165cb93a386Sopenharmony_ci                                                            nullptr,
166cb93a386Sopenharmony_ci                                                            SkIRect::MakeWH(kFullSize, kFullSize),
167cb93a386Sopenharmony_ci                                                            fullImage,
168cb93a386Sopenharmony_ci                                                            SkSurfaceProps()));
169cb93a386Sopenharmony_ci
170cb93a386Sopenharmony_ci    const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
171cb93a386Sopenharmony_ci
172cb93a386Sopenharmony_ci    {
173cb93a386Sopenharmony_ci        sk_sp<SkSpecialImage> subSImg1(SkSpecialImage::MakeFromImage(nullptr, subset, fullImage,
174cb93a386Sopenharmony_ci                                                                     SkSurfaceProps()));
175cb93a386Sopenharmony_ci        test_image(subSImg1, reporter, nullptr, false);
176cb93a386Sopenharmony_ci    }
177cb93a386Sopenharmony_ci
178cb93a386Sopenharmony_ci    {
179cb93a386Sopenharmony_ci        sk_sp<SkSpecialImage> subSImg2(fullSImage->makeSubset(subset));
180cb93a386Sopenharmony_ci        test_image(subSImg2, reporter, nullptr, false);
181cb93a386Sopenharmony_ci    }
182cb93a386Sopenharmony_ci}
183cb93a386Sopenharmony_ci
184cb93a386Sopenharmony_ciDEF_TEST(SpecialImage_Image_Legacy, reporter) {
185cb93a386Sopenharmony_ci    test_specialimage_image(reporter);
186cb93a386Sopenharmony_ci}
187cb93a386Sopenharmony_ci
188cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SpecialImage_Gpu, reporter, ctxInfo) {
189cb93a386Sopenharmony_ci    auto context = ctxInfo.directContext();
190cb93a386Sopenharmony_ci    SkBitmap bm = create_bm();
191cb93a386Sopenharmony_ci    auto [view, ct] = GrMakeUncachedBitmapProxyView(context, bm);
192cb93a386Sopenharmony_ci    if (!view) {
193cb93a386Sopenharmony_ci        return;
194cb93a386Sopenharmony_ci    }
195cb93a386Sopenharmony_ci
196cb93a386Sopenharmony_ci    sk_sp<SkSpecialImage> fullSImg =
197cb93a386Sopenharmony_ci            SkSpecialImage::MakeDeferredFromGpu(context,
198cb93a386Sopenharmony_ci                                                SkIRect::MakeWH(kFullSize, kFullSize),
199cb93a386Sopenharmony_ci                                                kNeedNewImageUniqueID_SpecialImage,
200cb93a386Sopenharmony_ci                                                view,
201cb93a386Sopenharmony_ci                                                ct,
202cb93a386Sopenharmony_ci                                                nullptr,
203cb93a386Sopenharmony_ci                                                SkSurfaceProps());
204cb93a386Sopenharmony_ci
205cb93a386Sopenharmony_ci    const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
206cb93a386Sopenharmony_ci
207cb93a386Sopenharmony_ci    {
208cb93a386Sopenharmony_ci        sk_sp<SkSpecialImage> subSImg1 = SkSpecialImage::MakeDeferredFromGpu(
209cb93a386Sopenharmony_ci                context,
210cb93a386Sopenharmony_ci                subset,
211cb93a386Sopenharmony_ci                kNeedNewImageUniqueID_SpecialImage,
212cb93a386Sopenharmony_ci                std::move(view),
213cb93a386Sopenharmony_ci                ct,
214cb93a386Sopenharmony_ci                nullptr,
215cb93a386Sopenharmony_ci                SkSurfaceProps());
216cb93a386Sopenharmony_ci        test_image(subSImg1, reporter, context, true);
217cb93a386Sopenharmony_ci    }
218cb93a386Sopenharmony_ci
219cb93a386Sopenharmony_ci    {
220cb93a386Sopenharmony_ci        sk_sp<SkSpecialImage> subSImg2 = fullSImg->makeSubset(subset);
221cb93a386Sopenharmony_ci        test_image(subSImg2, reporter, context, true);
222cb93a386Sopenharmony_ci    }
223cb93a386Sopenharmony_ci}
224