OLD | NEW |
| (Empty) |
1 | |
2 /* | |
3 * Copyright 2012 Google Inc. | |
4 * | |
5 * Use of this source code is governed by a BSD-style license that can be | |
6 * found in the LICENSE file. | |
7 */ | |
8 | |
9 #if SK_SUPPORT_GPU | |
10 | |
11 #include "GrContext.h" | |
12 #include "GrContextFactory.h" | |
13 #include "SkBitmap.h" | |
14 #include "SkCanvas.h" | |
15 #include "SkColor.h" | |
16 #include "SkGpuDevice.h" | |
17 #include "SkPaint.h" | |
18 #include "SkPixelRef.h" | |
19 #include "SkRect.h" | |
20 #include "Test.h" | |
21 | |
22 struct Pair { | |
23 SkColorType fColorType; | |
24 const char* fValid; | |
25 }; | |
26 | |
27 #ifdef SK_SUPPORT_DEEPCOPYTO_CONFIG | |
28 static const char* boolStr(bool value) { | |
29 return value ? "true" : "false"; | |
30 } | |
31 | |
32 // these are in the same order as the SkBitmap::Config enum | |
33 static const char* gColorTypeName[] = { | |
34 "None", "8888" | |
35 }; | |
36 | |
37 /** | |
38 * Check to ensure that copying a GPU-backed SkBitmap behaved as expected. | |
39 * @param reporter Used to report failures. | |
40 * @param desiredCT colorType being copied to. If the copy succeeded, dst must
have this Config. | |
41 * @param success True if the copy succeeded. | |
42 * @param src A GPU-backed SkBitmap that had copyTo or deepCopyTo called on it. | |
43 * @param dst SkBitmap that was copied to. | |
44 * @param expectSameGenID Whether the genIDs should be the same if success is t
rue. | |
45 */ | |
46 static void TestIndividualCopy(skiatest::Reporter* reporter, const SkColorType d
esiredCT, | |
47 const bool success, const SkBitmap& src, const Sk
Bitmap& dst, | |
48 const bool expectSameGenID) { | |
49 if (success) { | |
50 REPORTER_ASSERT(reporter, src.width() == dst.width()); | |
51 REPORTER_ASSERT(reporter, src.height() == dst.height()); | |
52 REPORTER_ASSERT(reporter, dst.colorType() == desiredCT); | |
53 if (src.config() == dst.config()) { | |
54 if (expectSameGenID) { | |
55 REPORTER_ASSERT(reporter, src.getGenerationID() == dst.getGenera
tionID()); | |
56 } else { | |
57 REPORTER_ASSERT(reporter, src.getGenerationID() != dst.getGenera
tionID()); | |
58 } | |
59 REPORTER_ASSERT(reporter, src.pixelRef() != NULL && dst.pixelRef() !
= NULL); | |
60 | |
61 // Do read backs and make sure that the two are the same. | |
62 SkBitmap srcReadBack, dstReadBack; | |
63 { | |
64 SkASSERT(src.getTexture() != NULL); | |
65 const SkIPoint origin = src.pixelRefOrigin(); | |
66 const SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, | |
67 src.width(), src.height
()); | |
68 bool readBack = src.pixelRef()->readPixels(&srcReadBack, &subset
); | |
69 REPORTER_ASSERT(reporter, readBack); | |
70 } | |
71 if (dst.getTexture() != NULL) { | |
72 const SkIPoint origin = dst.pixelRefOrigin(); | |
73 const SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, | |
74 dst.width(), dst.height
()); | |
75 bool readBack = dst.pixelRef()->readPixels(&dstReadBack, &subset
); | |
76 REPORTER_ASSERT(reporter, readBack); | |
77 } else { | |
78 // If dst is not a texture, do a copy instead, to the same confi
g as srcReadBack. | |
79 bool copy = dst.copyTo(&dstReadBack, srcReadBack.colorType()); | |
80 REPORTER_ASSERT(reporter, copy); | |
81 } | |
82 | |
83 SkAutoLockPixels srcLock(srcReadBack); | |
84 SkAutoLockPixels dstLock(dstReadBack); | |
85 REPORTER_ASSERT(reporter, srcReadBack.readyToDraw() && dstReadBack.r
eadyToDraw()); | |
86 | |
87 const char* srcP = static_cast<const char*>(srcReadBack.getAddr(0, 0
)); | |
88 const char* dstP = static_cast<const char*>(dstReadBack.getAddr(0, 0
)); | |
89 REPORTER_ASSERT(reporter, srcP != dstP); | |
90 | |
91 REPORTER_ASSERT(reporter, !memcmp(srcP, dstP, srcReadBack.getSize())
); | |
92 } else { | |
93 REPORTER_ASSERT(reporter, src.getGenerationID() != dst.getGeneration
ID()); | |
94 } | |
95 } else { | |
96 // dst should be unchanged from its initial state | |
97 REPORTER_ASSERT(reporter, dst.config() == SkBitmap::kNo_Config); | |
98 REPORTER_ASSERT(reporter, dst.width() == 0); | |
99 REPORTER_ASSERT(reporter, dst.height() == 0); | |
100 } | |
101 | |
102 } | |
103 #endif | |
104 | |
105 // Stripped down version of TestBitmapCopy that checks basic fields (width, heig
ht, config, genID) | |
106 // to ensure that they were copied properly. | |
107 DEF_GPUTEST(GpuBitmapCopy, reporter, factory) { | |
108 #ifdef SK_BUILD_FOR_ANDROID // https://code.google.com/p/skia/issues/detail?id=7
53 | |
109 return; | |
110 #endif | |
111 for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) { | |
112 GrContextFactory::GLContextType glType = static_cast<GrContextFactory::G
LContextType>(type); | |
113 if (!GrContextFactory::IsRenderingGLContext(glType)) { | |
114 continue; | |
115 } | |
116 | |
117 GrContext* grContext = factory->get(glType); | |
118 if (NULL == grContext) { | |
119 continue; | |
120 } | |
121 | |
122 | |
123 if (NULL == grContext) { | |
124 return; | |
125 } | |
126 static const Pair gPairs[] = { | |
127 // SkGpuDevice can no longer be Create()ed with kNo_Config | |
128 // (or kUnknown_SkColorType in the new world), hence much of this | |
129 // test will be skipped, since it was checking that calling | |
130 // copyTo or deepCopyTo with src or dst set to kUnknown/kNo would | |
131 // successfully fail. | |
132 // | |
133 // If we can declare that you can *never* create a texture with | |
134 // kUnknown, then perhaps we can remove this entire test... | |
135 // | |
136 // { SkBitmap::kNo_Config, "00" }, | |
137 // { SkBitmap::kARGB_8888_Config, "01" }, | |
138 { kPMColor_SkColorType, "1" }, | |
139 }; | |
140 | |
141 const int W = 20; | |
142 const int H = 33; | |
143 | |
144 for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) { | |
145 SkImageInfo info = SkImageInfo::Make(W, H, | |
146 gPairs[i].fColorType, | |
147 kPremul_SkAlphaType); | |
148 SkBitmap src, dst; | |
149 | |
150 SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(grContext, info
, 0)); | |
151 SkASSERT(device.get()); | |
152 | |
153 src = device->accessBitmap(false); | |
154 device->clear(SK_ColorWHITE); | |
155 | |
156 // Draw something different to the same portion of the bitmap that w
e will extract as a | |
157 // subset, so that comparing the pixels of the subset will be meanin
gful. | |
158 SkIRect subsetRect = SkIRect::MakeLTRB(W/2, H/2, W, H); | |
159 SkCanvas drawingCanvas(device); | |
160 SkPaint paint; | |
161 paint.setColor(SK_ColorRED); | |
162 drawingCanvas.drawRect(SkRect::Make(subsetRect), paint); | |
163 | |
164 // Extract a subset. If this succeeds we will test copying the subse
t. | |
165 SkBitmap subset; | |
166 #ifdef SK_SUPPORT_DEEPCOPYTO_CONFIG | |
167 const bool extracted = src.extractSubset(&subset, subsetRect); | |
168 | |
169 for (size_t j = 0; j < SK_ARRAY_COUNT(gPairs); j++) { | |
170 SkBitmap::Config pairsConfig = SkColorTypeToBitmapConfig(gPairs[
j].fColorType); | |
171 dst.reset(); | |
172 bool success = src.deepCopyTo(&dst, pairsConfig); | |
173 bool expected = gPairs[i].fValid[j] != '0'; | |
174 if (success != expected) { | |
175 ERRORF(reporter, "SkBitmap::deepCopyTo from %s to %s. " | |
176 "expected %s returned %s", gColorTypeName[i], | |
177 gColorTypeName[j], boolStr(expected), | |
178 boolStr(success)); | |
179 } | |
180 | |
181 bool canSucceed = src.canCopyTo(gPairs[j].fColorType); | |
182 if (success != canSucceed) { | |
183 ERRORF(reporter, "SkBitmap::deepCopyTo from %s to %s " | |
184 "returned %s, but canCopyTo returned %s", | |
185 gColorTypeName[i], gColorTypeName[j], boolStr(success
), | |
186 boolStr(canSucceed)); | |
187 } | |
188 | |
189 TestIndividualCopy(reporter, gPairs[j].fColorType, success, src,
dst, true); | |
190 | |
191 // Test copying the subset bitmap, using both copyTo and deepCop
yTo. | |
192 if (extracted) { | |
193 SkBitmap subsetCopy; | |
194 success = subset.copyTo(&subsetCopy, gPairs[j].fColorType); | |
195 REPORTER_ASSERT(reporter, success == expected); | |
196 REPORTER_ASSERT(reporter, success == canSucceed); | |
197 TestIndividualCopy(reporter, gPairs[j].fColorType, success,
subset, subsetCopy, | |
198 true); | |
199 | |
200 // Reset the bitmap so that a failed copyTo will leave it in
the expected state. | |
201 subsetCopy.reset(); | |
202 success = subset.deepCopyTo(&subsetCopy, pairsConfig); | |
203 REPORTER_ASSERT(reporter, success == expected); | |
204 REPORTER_ASSERT(reporter, success == canSucceed); | |
205 TestIndividualCopy(reporter, gPairs[j].fColorType, success,
subset, subsetCopy, | |
206 true); | |
207 | |
208 // Now set a bitmap to be a subset that will share the same
pixelref. | |
209 // This allows testing another case of cloning the genID. Wh
en calling copyTo | |
210 // on a bitmap representing a subset of its pixelref, the re
sulting pixelref | |
211 // should not share the genID, since we only copied the subs
et. | |
212 SkBitmap trueSubset; | |
213 // FIXME: Once https://codereview.chromium.org/109023008/ la
nds, call | |
214 // trueSubset.installPixelRef(src.pixelRef(), subset); | |
215 trueSubset.setConfig(SkImageInfo::Make(W/2, H/2, gPairs[i].f
ColorType, | |
216 kPremul_SkAlphaType))
; | |
217 trueSubset.setPixelRef(src.pixelRef(), W/2, H/2); | |
218 | |
219 subsetCopy.reset(); | |
220 success = trueSubset.copyTo(&subsetCopy, gPairs[j].fColorTyp
e); | |
221 REPORTER_ASSERT(reporter, success == expected); | |
222 REPORTER_ASSERT(reporter, success == canSucceed); | |
223 TestIndividualCopy(reporter, gPairs[j].fColorType, success,
trueSubset, subsetCopy, | |
224 false); | |
225 | |
226 // deepCopyTo copies the entire pixelref, even if the bitmap
only represents | |
227 // a subset. Therefore, the result should share the same gen
ID. | |
228 subsetCopy.reset(); | |
229 success = trueSubset.deepCopyTo(&subsetCopy, pairsConfig); | |
230 REPORTER_ASSERT(reporter, success == expected); | |
231 REPORTER_ASSERT(reporter, success == canSucceed); | |
232 TestIndividualCopy(reporter, gPairs[j].fColorType, success,
trueSubset, subsetCopy, | |
233 true); | |
234 } | |
235 } // for (size_t j = ... | |
236 #endif | |
237 } // for (size_t i = ... | |
238 } // GrContextFactory::GLContextType | |
239 } | |
240 | |
241 #endif | |
OLD | NEW |