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