blob: 233ce2cee18338a4e2fcc6157028ffb1de5ee640 [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)
robertphillips37bd7c32016-03-17 14:31:39 -070052static void test_image(const sk_sp<SkSpecialImage>& img, skiatest::Reporter* reporter,
robertphillipsc5035e72016-03-17 06:58:39 -070053 bool peekPixelsSucceeds, bool peekTextureSucceeds,
54 int offset, int size) {
robertphillips37bd7c32016-03-17 14:31:39 -070055 const SkIRect subset = TestingSpecialImageAccess::Subset(img.get());
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 //--------------
robertphillips37bd7c32016-03-17 14:31:39 -070062 REPORTER_ASSERT(reporter, peekTextureSucceeds ==
63 !!TestingSpecialImageAccess::PeekTexture(img.get()));
robertphillipsb6c65e92016-02-04 10:52:42 -080064
65 //--------------
66 SkPixmap pixmap;
67 REPORTER_ASSERT(reporter, peekPixelsSucceeds ==
robertphillips37bd7c32016-03-17 14:31:39 -070068 !!TestingSpecialImageAccess::PeekPixels(img.get(), &pixmap));
robertphillipsb6c65e92016-02-04 10:52:42 -080069 if (peekPixelsSucceeds) {
robertphillipsc5035e72016-03-17 06:58:39 -070070 REPORTER_ASSERT(reporter, size == pixmap.width());
71 REPORTER_ASSERT(reporter, size == pixmap.height());
robertphillipsb6c65e92016-02-04 10:52:42 -080072 }
73
74 //--------------
75 SkImageInfo info = SkImageInfo::MakeN32(kFullSize, kFullSize, kOpaque_SkAlphaType);
76
robertphillips37bd7c32016-03-17 14:31:39 -070077 sk_sp<SkSpecialSurface> surf(img->makeSurface(info));
robertphillipsb6c65e92016-02-04 10:52:42 -080078
79 SkCanvas* canvas = surf->getCanvas();
80
81 canvas->clear(SK_ColorBLUE);
robertphillipse8c34972016-02-16 12:09:36 -080082 img->draw(canvas, SkIntToScalar(kPad), SkIntToScalar(kPad), nullptr);
robertphillipsb6c65e92016-02-04 10:52:42 -080083
84 SkBitmap bm;
85 bm.allocN32Pixels(kFullSize, kFullSize, true);
86
87 bool result = canvas->readPixels(bm.info(), bm.getPixels(), bm.rowBytes(), 0, 0);
88 SkASSERT_RELEASE(result);
89
90 // Only the center (red) portion should've been drawn into the canvas
91 REPORTER_ASSERT(reporter, SK_ColorBLUE == bm.getColor(kPad-1, kPad-1));
92 REPORTER_ASSERT(reporter, SK_ColorRED == bm.getColor(kPad, kPad));
93 REPORTER_ASSERT(reporter, SK_ColorRED == bm.getColor(kSmallerSize+kPad-1,
94 kSmallerSize+kPad-1));
95 REPORTER_ASSERT(reporter, SK_ColorBLUE == bm.getColor(kSmallerSize+kPad,
96 kSmallerSize+kPad));
97}
98
99DEF_TEST(SpecialImage_Raster, reporter) {
100 SkBitmap bm = create_bm();
101
robertphillips37bd7c32016-03-17 14:31:39 -0700102 sk_sp<SkSpecialImage> fullSImage(SkSpecialImage::MakeFromRaster(
robertphillipsc5035e72016-03-17 06:58:39 -0700103 nullptr,
104 SkIRect::MakeWH(kFullSize, kFullSize),
105 bm));
106
robertphillipsb6c65e92016-02-04 10:52:42 -0800107 const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
108
robertphillipsc5035e72016-03-17 06:58:39 -0700109 {
robertphillips37bd7c32016-03-17 14:31:39 -0700110 sk_sp<SkSpecialImage> subSImg1(SkSpecialImage::MakeFromRaster(nullptr, subset, bm));
robertphillipsc5035e72016-03-17 06:58:39 -0700111 test_image(subSImg1, reporter, true, false, kPad, kFullSize);
112 }
113
114 {
robertphillips37bd7c32016-03-17 14:31:39 -0700115 sk_sp<SkSpecialImage> subSImg2(fullSImage->makeSubset(subset));
robertphillipsc5035e72016-03-17 06:58:39 -0700116 test_image(subSImg2, reporter, true, false, 0, kSmallerSize);
117 }
robertphillipsb6c65e92016-02-04 10:52:42 -0800118}
119
120DEF_TEST(SpecialImage_Image, reporter) {
121 SkBitmap bm = create_bm();
122
reed9ce9d672016-03-17 10:51:11 -0700123 sk_sp<SkImage> fullImage(SkImage::MakeFromBitmap(bm));
robertphillipsb6c65e92016-02-04 10:52:42 -0800124
robertphillips37bd7c32016-03-17 14:31:39 -0700125 sk_sp<SkSpecialImage> fullSImage(SkSpecialImage::MakeFromImage(
robertphillipsc5035e72016-03-17 06:58:39 -0700126 nullptr,
127 SkIRect::MakeWH(kFullSize, kFullSize),
robertphillips37bd7c32016-03-17 14:31:39 -0700128 fullImage));
robertphillipsc5035e72016-03-17 06:58:39 -0700129
robertphillipsb6c65e92016-02-04 10:52:42 -0800130 const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
131
robertphillipsc5035e72016-03-17 06:58:39 -0700132 {
robertphillips37bd7c32016-03-17 14:31:39 -0700133 sk_sp<SkSpecialImage> subSImg1(SkSpecialImage::MakeFromImage(nullptr, subset,
134 fullImage));
robertphillipsc5035e72016-03-17 06:58:39 -0700135 test_image(subSImg1, reporter, true, false, kPad, kFullSize);
136 }
137
138 {
robertphillips37bd7c32016-03-17 14:31:39 -0700139 sk_sp<SkSpecialImage> subSImg2(fullSImage->makeSubset(subset));
robertphillipsc5035e72016-03-17 06:58:39 -0700140 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
robertphillips37bd7c32016-03-17 14:31:39 -0700157 sk_sp<SkSpecialImage> img(SkSpecialImage::MakeFromPixmap(nullptr, subset, pixmap,
158 nullptr, nullptr));
robertphillipsc5035e72016-03-17 06:58:39 -0700159 test_image(img, reporter, true, false, kPad, kFullSize);
160 }
161
162 {
163 // The image takes ownership of the memory
robertphillips37bd7c32016-03-17 14:31:39 -0700164 sk_sp<SkSpecialImage> img(SkSpecialImage::MakeFromPixmap(
robertphillipsc5035e72016-03-17 06:58:39 -0700165 nullptr, subset, pixmap,
robertphillips37bd7c32016-03-17 14:31:39 -0700166 [] (void* addr, void*) -> void {
167 sk_free(addr);
168 },
robertphillipsc5035e72016-03-17 06:58:39 -0700169 nullptr));
170 pixmap.release();
171 test_image(img, reporter, true, false, kPad, kFullSize);
172 }
173}
174
175
robertphillipsb6c65e92016-02-04 10:52:42 -0800176#if SK_SUPPORT_GPU
177DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SpecialImage_Gpu, reporter, context) {
178 SkBitmap bm = create_bm();
179
180 GrSurfaceDesc desc;
181 desc.fConfig = kSkia8888_GrPixelConfig;
182 desc.fFlags = kNone_GrSurfaceFlags;
183 desc.fWidth = kFullSize;
184 desc.fHeight = kFullSize;
185
bsalomon5ec26ae2016-02-25 08:33:02 -0800186 SkAutoTUnref<GrTexture> texture(context->textureProvider()->createTexture(desc, SkBudgeted::kNo,
robertphillipsb6c65e92016-02-04 10:52:42 -0800187 bm.getPixels(), 0));
188 if (!texture) {
189 return;
190 }
191
robertphillips37bd7c32016-03-17 14:31:39 -0700192 sk_sp<SkSpecialImage> fullSImg(SkSpecialImage::MakeFromGpu(
robertphillipsc5035e72016-03-17 06:58:39 -0700193 nullptr,
194 SkIRect::MakeWH(kFullSize, kFullSize),
195 kNeedNewImageUniqueID_SpecialImage,
196 texture));
197
robertphillipsb6c65e92016-02-04 10:52:42 -0800198 const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
199
robertphillipsc5035e72016-03-17 06:58:39 -0700200 {
robertphillips37bd7c32016-03-17 14:31:39 -0700201 sk_sp<SkSpecialImage> subSImg1(SkSpecialImage::MakeFromGpu(
robertphillipsc5035e72016-03-17 06:58:39 -0700202 nullptr, subset,
203 kNeedNewImageUniqueID_SpecialImage,
204 texture));
205 test_image(subSImg1, reporter, false, true, kPad, kFullSize);
206 }
207
208 {
robertphillips37bd7c32016-03-17 14:31:39 -0700209 sk_sp<SkSpecialImage> subSImg2(fullSImg->makeSubset(subset));
robertphillipsc5035e72016-03-17 06:58:39 -0700210 test_image(subSImg2, reporter, false, true, kPad, kFullSize);
211 }
robertphillipsb6c65e92016-02-04 10:52:42 -0800212}
213
214#endif