| 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 |