blob: 03a496dbbaf747b669212efff94abb6ce98fd254 [file] [log] [blame]
robertphillipsb6c65e92016-02-04 10:52:42 -08001/*
2 * Copyright 2016 Google Inc.
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
robertphillipsc5035e72016-03-17 06:58:39 -07008#include "SkAutoPixmapStorage.h"
robertphillipsb6c65e92016-02-04 10:52:42 -08009#include "SkBitmap.h"
10#include "SkCanvas.h"
11#include "SkImage.h"
robertphillipsc5035e72016-03-17 06:58:39 -070012#include "SkPixmap.h"
robertphillipsb6c65e92016-02-04 10:52:42 -080013#include "SkSpecialImage.h"
14#include "SkSpecialSurface.h"
15#include "Test.h"
robertphillips4418dba2016-03-07 12:45:14 -080016#include "TestingSpecialImageAccess.h"
robertphillipsb6c65e92016-02-04 10:52:42 -080017
18#if SK_SUPPORT_GPU
19#include "GrContext.h"
20#endif
21
robertphillipsb6c65e92016-02-04 10:52:42 -080022
23// This test creates backing resources exactly sized to [kFullSize x kFullSize].
24// It then wraps them in an SkSpecialImage with only the center (red) region being active.
25// It then draws the SkSpecialImage to a full sized (all blue) canvas and checks that none
26// of the inactive (green) region leaked out.
27
28static const int kSmallerSize = 10;
29static const int kPad = 3;
30static const int kFullSize = kSmallerSize + 2 * kPad;
31
32// Create a bitmap with red in the center and green around it
33static SkBitmap create_bm() {
34 SkBitmap bm;
35 bm.allocN32Pixels(kFullSize, kFullSize, true);
36
37 SkCanvas temp(bm);
38
39 temp.clear(SK_ColorGREEN);
40 SkPaint p;
41 p.setColor(SK_ColorRED);
42 p.setAntiAlias(false);
43
44 temp.drawRect(SkRect::MakeXYWH(SkIntToScalar(kPad), SkIntToScalar(kPad),
45 SkIntToScalar(kSmallerSize), SkIntToScalar(kSmallerSize)),
46 p);
47
48 return bm;
49}
50
51// Basic test of the SkSpecialImage public API (e.g., peekTexture, peekPixels & draw)
52static void test_image(SkSpecialImage* img, skiatest::Reporter* reporter,
robertphillipsc5035e72016-03-17 06:58:39 -070053 bool peekPixelsSucceeds, bool peekTextureSucceeds,
54 int offset, int size) {
robertphillipsb6c65e92016-02-04 10:52:42 -080055 const SkIRect subset = TestingSpecialImageAccess::Subset(img);
robertphillipsc5035e72016-03-17 06:58:39 -070056 REPORTER_ASSERT(reporter, offset == subset.left());
57 REPORTER_ASSERT(reporter, offset == subset.top());
robertphillipsb6c65e92016-02-04 10:52:42 -080058 REPORTER_ASSERT(reporter, kSmallerSize == subset.width());
59 REPORTER_ASSERT(reporter, kSmallerSize == subset.height());
60
61 //--------------
62 REPORTER_ASSERT(reporter, peekTextureSucceeds == !!TestingSpecialImageAccess::PeekTexture(img));
63
64 //--------------
65 SkPixmap pixmap;
66 REPORTER_ASSERT(reporter, peekPixelsSucceeds ==
67 !!TestingSpecialImageAccess::PeekPixels(img, &pixmap));
68 if (peekPixelsSucceeds) {
robertphillipsc5035e72016-03-17 06:58:39 -070069 REPORTER_ASSERT(reporter, size == pixmap.width());
70 REPORTER_ASSERT(reporter, size == pixmap.height());
robertphillipsb6c65e92016-02-04 10:52:42 -080071 }
72
73 //--------------
74 SkImageInfo info = SkImageInfo::MakeN32(kFullSize, kFullSize, kOpaque_SkAlphaType);
75
76 SkAutoTUnref<SkSpecialSurface> surf(img->newSurface(info));
77
78 SkCanvas* canvas = surf->getCanvas();
79
80 canvas->clear(SK_ColorBLUE);
robertphillipse8c34972016-02-16 12:09:36 -080081 img->draw(canvas, SkIntToScalar(kPad), SkIntToScalar(kPad), nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -080082
83 SkBitmap bm;
84 bm.allocN32Pixels(kFullSize, kFullSize, true);
85
86 bool result = canvas->readPixels(bm.info(), bm.getPixels(), bm.rowBytes(), 0, 0);
87 SkASSERT_RELEASE(result);
88
89 // Only the center (red) portion should've been drawn into the canvas
90 REPORTER_ASSERT(reporter, SK_ColorBLUE == bm.getColor(kPad-1, kPad-1));
91 REPORTER_ASSERT(reporter, SK_ColorRED == bm.getColor(kPad, kPad));
92 REPORTER_ASSERT(reporter, SK_ColorRED == bm.getColor(kSmallerSize+kPad-1,
93 kSmallerSize+kPad-1));
94 REPORTER_ASSERT(reporter, SK_ColorBLUE == bm.getColor(kSmallerSize+kPad,
95 kSmallerSize+kPad));
96}
97
98DEF_TEST(SpecialImage_Raster, reporter) {
99 SkBitmap bm = create_bm();
100
robertphillipsc5035e72016-03-17 06:58:39 -0700101 SkAutoTUnref<SkSpecialImage> fullSImage(SkSpecialImage::NewFromRaster(
102 nullptr,
103 SkIRect::MakeWH(kFullSize, kFullSize),
104 bm));
105
robertphillipsb6c65e92016-02-04 10:52:42 -0800106 const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
107
robertphillipsc5035e72016-03-17 06:58:39 -0700108 {
109 SkAutoTUnref<SkSpecialImage> subSImg1(SkSpecialImage::NewFromRaster(nullptr, subset, bm));
110 test_image(subSImg1, reporter, true, false, kPad, kFullSize);
111 }
112
113 {
114 SkAutoTUnref<SkSpecialImage> subSImg2(fullSImage->extractSubset(subset));
115 test_image(subSImg2, reporter, true, false, 0, kSmallerSize);
116 }
robertphillipsb6c65e92016-02-04 10:52:42 -0800117}
118
119DEF_TEST(SpecialImage_Image, reporter) {
120 SkBitmap bm = create_bm();
121
reed9ce9d672016-03-17 10:51:11 -0700122 sk_sp<SkImage> fullImage(SkImage::MakeFromBitmap(bm));
robertphillipsb6c65e92016-02-04 10:52:42 -0800123
robertphillipsc5035e72016-03-17 06:58:39 -0700124 SkAutoTUnref<SkSpecialImage> fullSImage(SkSpecialImage::NewFromImage(
125 nullptr,
126 SkIRect::MakeWH(kFullSize, kFullSize),
reed9ce9d672016-03-17 10:51:11 -0700127 fullImage.get()));
robertphillipsc5035e72016-03-17 06:58:39 -0700128
robertphillipsb6c65e92016-02-04 10:52:42 -0800129 const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
130
robertphillipsc5035e72016-03-17 06:58:39 -0700131 {
132 SkAutoTUnref<SkSpecialImage> subSImg1(SkSpecialImage::NewFromImage(nullptr,
133 subset,
reed9ce9d672016-03-17 10:51:11 -0700134 fullImage.get()));
robertphillipsc5035e72016-03-17 06:58:39 -0700135 test_image(subSImg1, reporter, true, false, kPad, kFullSize);
136 }
137
138 {
139 SkAutoTUnref<SkSpecialImage> subSImg2(fullSImage->extractSubset(subset));
140 test_image(subSImg2, reporter, true, false, 0, kSmallerSize);
141 }
robertphillipsb6c65e92016-02-04 10:52:42 -0800142}
143
robertphillipsc5035e72016-03-17 06:58:39 -0700144DEF_TEST(SpecialImage_Pixmap, reporter) {
145 SkAutoPixmapStorage pixmap;
146
147 const SkImageInfo info = SkImageInfo::MakeN32(kFullSize, kFullSize, kOpaque_SkAlphaType);
148 pixmap.alloc(info);
149 pixmap.erase(SK_ColorGREEN);
150
151 const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
152
153 pixmap.erase(SK_ColorRED, subset);
154
155 {
156 // The SkAutoPixmapStorage keeps hold of the memory
157 SkAutoTUnref<SkSpecialImage> img(SkSpecialImage::NewFromPixmap(nullptr, subset, pixmap,
158 nullptr, nullptr));
159 test_image(img, reporter, true, false, kPad, kFullSize);
160 }
161
162 {
163 // The image takes ownership of the memory
164 SkAutoTUnref<SkSpecialImage> img(SkSpecialImage::NewFromPixmap(
165 nullptr, subset, pixmap,
166 [] (void* addr, void*) -> void { sk_free(addr); },
167 nullptr));
168 pixmap.release();
169 test_image(img, reporter, true, false, kPad, kFullSize);
170 }
171}
172
173
robertphillipsb6c65e92016-02-04 10:52:42 -0800174#if SK_SUPPORT_GPU
175DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SpecialImage_Gpu, reporter, context) {
176 SkBitmap bm = create_bm();
177
178 GrSurfaceDesc desc;
179 desc.fConfig = kSkia8888_GrPixelConfig;
180 desc.fFlags = kNone_GrSurfaceFlags;
181 desc.fWidth = kFullSize;
182 desc.fHeight = kFullSize;
183
bsalomon5ec26ae2016-02-25 08:33:02 -0800184 SkAutoTUnref<GrTexture> texture(context->textureProvider()->createTexture(desc, SkBudgeted::kNo,
robertphillipsb6c65e92016-02-04 10:52:42 -0800185 bm.getPixels(), 0));
186 if (!texture) {
187 return;
188 }
189
robertphillipsc5035e72016-03-17 06:58:39 -0700190 SkAutoTUnref<SkSpecialImage> fullSImg(SkSpecialImage::NewFromGpu(
191 nullptr,
192 SkIRect::MakeWH(kFullSize, kFullSize),
193 kNeedNewImageUniqueID_SpecialImage,
194 texture));
195
robertphillipsb6c65e92016-02-04 10:52:42 -0800196 const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
197
robertphillipsc5035e72016-03-17 06:58:39 -0700198 {
199 SkAutoTUnref<SkSpecialImage> subSImg1(SkSpecialImage::NewFromGpu(
200 nullptr, subset,
201 kNeedNewImageUniqueID_SpecialImage,
202 texture));
203 test_image(subSImg1, reporter, false, true, kPad, kFullSize);
204 }
205
206 {
207 SkAutoTUnref<SkSpecialImage> subSImg2(fullSImg->extractSubset(subset));
208 test_image(subSImg2, reporter, false, true, kPad, kFullSize);
209 }
robertphillipsb6c65e92016-02-04 10:52:42 -0800210}
211
212#endif