aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests
diff options
context:
space:
mode:
authorGravatar scroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-01-15 16:56:52 +0000
committerGravatar scroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-01-15 16:56:52 +0000
commit5ccae2c5b134d1b971c188215433305e88491aec (patch)
treedce979407d9f01c1e5777bac01d870855ec2fd67 /tests
parent9fcd012f8c985830e75b2295fd2c9aa068dd1a80 (diff)
Reland "Fix genID cloning bugs."
SkBitmap.cpp: When copyTo calls readPixels, only clone the genID if the resulting SkPixelRef has the same dimensions as the original. This catches a bug where copying an SkBitmap representing the subset of an SkPixelRef (which implements onReadPixels) would result in the copy sharing the genID. (Thanks to r6710, this case can only happen using setPixelRef, so the updated GpuBitmapCopyTest checks for that.) Move some unnecessary NULL checks to asserts. When copyTo performs a memcpy, only clone the genID if the resulting SkPixelRef has the same dimensions as the original. This catches a bug where copying an extracted SkBitmap with the same width as its original SkPixelRef would incorrectly have the same genID. Add a comment and assert in deepCopyTo, when cloning the genID, since that case correctly clones it. BitmapCopyTest.cpp: Pull redundant work out of the inner loop (setting up the source bitmaps and testing extractSubset). Create a new inner loop for extractSubset, to test copying the result to each different config. Extract a subset that has the same width as the original, to catch the bug mentioned above. Remove the reporter assert which checks for the resulting rowbytes. Add checks to ensure that copying the extracted subset changes the genID. GpuBitmapCopyTest: Create an SkBitmap that shares an existing SkPixelRef, but only represents a subset. This is to test the first call to cloneGenID in SkBitmap::copyTo. In this case, the genID should NOT be copied, since only a portion of the SkPixelRef was copied. Also test deepCopy on this subset. TestIndividualCopy now takes a parameter stating whether the genID should change in the copy. It also does a read back using the appropriate subset. It no longer differentiates between copyTo and deepCopyTo, since that distinction was only necessary for copying from/to configs other than 8888 (which are no longer being tested), where copyTo did a read back in 8888 and then drew the result to the desired config (resulting in an imperfect copy). BUG=skia:1742 Committed: http://code.google.com/p/skia/source/detail?r=13021 R=mtklein@google.com Review URL: https://codereview.chromium.org/112113005 git-svn-id: http://skia.googlecode.com/svn/trunk@13090 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'tests')
-rw-r--r--tests/BitmapCopyTest.cpp158
-rw-r--r--tests/GpuBitmapCopyTest.cpp52
2 files changed, 130 insertions, 80 deletions
diff --git a/tests/BitmapCopyTest.cpp b/tests/BitmapCopyTest.cpp
index 7f78392cea..9e96c33a42 100644
--- a/tests/BitmapCopyTest.cpp
+++ b/tests/BitmapCopyTest.cpp
@@ -1,4 +1,3 @@
-
/*
* Copyright 2011 Google Inc.
*
@@ -199,44 +198,103 @@ static void writeCoordPixels(SkBitmap& bm, const Coordinates& coords) {
setPixel(coords[i]->fX, coords[i]->fY, i, bm);
}
-DEF_TEST(BitmapCopy, reporter) {
- static const Pair gPairs[] = {
- { SkBitmap::kNo_Config, "0000000" },
- { SkBitmap::kA8_Config, "0101010" },
- { SkBitmap::kIndex8_Config, "0111010" },
- { SkBitmap::kRGB_565_Config, "0101010" },
- { SkBitmap::kARGB_4444_Config, "0101110" },
- { SkBitmap::kARGB_8888_Config, "0101110" },
- };
+static const Pair gPairs[] = {
+ { SkBitmap::kNo_Config, "0000000" },
+ { SkBitmap::kA8_Config, "0101010" },
+ { SkBitmap::kIndex8_Config, "0111010" },
+ { SkBitmap::kRGB_565_Config, "0101010" },
+ { SkBitmap::kARGB_4444_Config, "0101110" },
+ { SkBitmap::kARGB_8888_Config, "0101110" },
+};
- static const bool isExtracted[] = {
- false, true
- };
+static const int W = 20;
+static const int H = 33;
- const int W = 20;
- const int H = 33;
+static void setup_src_bitmaps(SkBitmap* srcOpaque, SkBitmap* srcPremul,
+ SkBitmap::Config config) {
+ SkColorTable* ctOpaque = NULL;
+ SkColorTable* ctPremul = NULL;
+ srcOpaque->setConfig(config, W, H, 0, kOpaque_SkAlphaType);
+ srcPremul->setConfig(config, W, H, 0, kPremul_SkAlphaType);
+ if (SkBitmap::kIndex8_Config == config) {
+ ctOpaque = init_ctable(kOpaque_SkAlphaType);
+ ctPremul = init_ctable(kPremul_SkAlphaType);
+ }
+ srcOpaque->allocPixels(ctOpaque);
+ srcPremul->allocPixels(ctPremul);
+ SkSafeUnref(ctOpaque);
+ SkSafeUnref(ctPremul);
+ init_src(*srcOpaque);
+ init_src(*srcPremul);
+}
+
+DEF_TEST(BitmapCopy_extractSubset, reporter) {
for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
- for (size_t j = 0; j < SK_ARRAY_COUNT(gPairs); j++) {
- SkBitmap srcOpaque, srcPremul, dst;
+ SkBitmap srcOpaque, srcPremul;
+ setup_src_bitmaps(&srcOpaque, &srcPremul, gPairs[i].fConfig);
+
+ SkBitmap bitmap(srcOpaque);
+ SkBitmap subset;
+ SkIRect r;
+ // Extract a subset which has the same width as the original. This
+ // catches a bug where we cloned the genID incorrectly.
+ r.set(0, 1, W, 3);
+ bitmap.setIsVolatile(true);
+ if (bitmap.extractSubset(&subset, r)) {
+ REPORTER_ASSERT(reporter, subset.width() == W);
+ REPORTER_ASSERT(reporter, subset.height() == 2);
+ REPORTER_ASSERT(reporter, subset.alphaType() == bitmap.alphaType());
+ REPORTER_ASSERT(reporter, subset.isVolatile() == true);
+
+ // Test copying an extracted subset.
+ for (size_t j = 0; j < SK_ARRAY_COUNT(gPairs); j++) {
+ SkBitmap copy;
+ bool success = subset.copyTo(&copy, gPairs[j].fConfig);
+ if (!success) {
+ // Skip checking that success matches fValid, which is redundant
+ // with the code below.
+ REPORTER_ASSERT(reporter, gPairs[i].fConfig != gPairs[j].fConfig);
+ continue;
+ }
- {
- SkColorTable* ctOpaque = NULL;
- SkColorTable* ctPremul = NULL;
+ // When performing a copy of an extracted subset, the gen id should
+ // change.
+ REPORTER_ASSERT(reporter, copy.getGenerationID() != subset.getGenerationID());
- srcOpaque.setConfig(gPairs[i].fConfig, W, H, 0, kOpaque_SkAlphaType);
- srcPremul.setConfig(gPairs[i].fConfig, W, H, 0, kPremul_SkAlphaType);
- if (SkBitmap::kIndex8_Config == gPairs[i].fConfig) {
- ctOpaque = init_ctable(kOpaque_SkAlphaType);
- ctPremul = init_ctable(kPremul_SkAlphaType);
+ REPORTER_ASSERT(reporter, copy.width() == W);
+ REPORTER_ASSERT(reporter, copy.height() == 2);
+
+ if (gPairs[i].fConfig == gPairs[j].fConfig) {
+ SkAutoLockPixels alp0(subset);
+ SkAutoLockPixels alp1(copy);
+ // they should both have, or both not-have, a colortable
+ bool hasCT = subset.getColorTable() != NULL;
+ REPORTER_ASSERT(reporter, (copy.getColorTable() != NULL) == hasCT);
}
- srcOpaque.allocPixels(ctOpaque);
- srcPremul.allocPixels(ctPremul);
- SkSafeUnref(ctOpaque);
- SkSafeUnref(ctPremul);
}
- init_src(srcOpaque);
- init_src(srcPremul);
+ }
+
+ bitmap = srcPremul;
+ bitmap.setIsVolatile(false);
+ if (bitmap.extractSubset(&subset, r)) {
+ REPORTER_ASSERT(reporter, subset.alphaType() == bitmap.alphaType());
+ REPORTER_ASSERT(reporter, subset.isVolatile() == false);
+ }
+ }
+}
+
+DEF_TEST(BitmapCopy, reporter) {
+ static const bool isExtracted[] = {
+ false, true
+ };
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
+ SkBitmap srcOpaque, srcPremul;
+ setup_src_bitmaps(&srcOpaque, &srcPremul, gPairs[i].fConfig);
+
+ for (size_t j = 0; j < SK_ARRAY_COUNT(gPairs); j++) {
+ SkBitmap dst;
bool success = srcPremul.copyTo(&dst, gPairs[j].fConfig);
bool expected = gPairs[i].fValid[j] != '0';
@@ -272,44 +330,6 @@ DEF_TEST(BitmapCopy, reporter) {
} else {
REPORTER_ASSERT(reporter, srcPremul.getGenerationID() != dst.getGenerationID());
}
- // test extractSubset
- {
- SkBitmap bitmap(srcOpaque);
- SkBitmap subset;
- SkIRect r;
- r.set(1, 1, 2, 2);
- bitmap.setIsVolatile(true);
- if (bitmap.extractSubset(&subset, r)) {
- REPORTER_ASSERT(reporter, subset.width() == 1);
- REPORTER_ASSERT(reporter, subset.height() == 1);
- REPORTER_ASSERT(reporter,
- subset.alphaType() == bitmap.alphaType());
- REPORTER_ASSERT(reporter,
- subset.isVolatile() == true);
-
- SkBitmap copy;
- REPORTER_ASSERT(reporter,
- subset.copyTo(&copy, subset.config()));
- REPORTER_ASSERT(reporter, copy.width() == 1);
- REPORTER_ASSERT(reporter, copy.height() == 1);
- REPORTER_ASSERT(reporter, copy.rowBytes() <= 4);
-
- SkAutoLockPixels alp0(subset);
- SkAutoLockPixels alp1(copy);
- // they should both have, or both not-have, a colortable
- bool hasCT = subset.getColorTable() != NULL;
- REPORTER_ASSERT(reporter,
- (copy.getColorTable() != NULL) == hasCT);
- }
- bitmap = srcPremul;
- bitmap.setIsVolatile(false);
- if (bitmap.extractSubset(&subset, r)) {
- REPORTER_ASSERT(reporter,
- subset.alphaType() == bitmap.alphaType());
- REPORTER_ASSERT(reporter,
- subset.isVolatile() == false);
- }
- }
} else {
// dst should be unchanged from its initial state
REPORTER_ASSERT(reporter, dst.config() == SkBitmap::kNo_Config);
diff --git a/tests/GpuBitmapCopyTest.cpp b/tests/GpuBitmapCopyTest.cpp
index 681ea6995b..fb81e2b74c 100644
--- a/tests/GpuBitmapCopyTest.cpp
+++ b/tests/GpuBitmapCopyTest.cpp
@@ -40,22 +40,20 @@ struct Pair {
* @param success True if the copy succeeded.
* @param src A GPU-backed SkBitmap that had copyTo or deepCopyTo called on it.
* @param dst SkBitmap that was copied to.
- * @param deepCopy True if deepCopyTo was used; false if copyTo was used.
+ * @param expectSameGenID Whether the genIDs should be the same if success is true.
*/
static void TestIndividualCopy(skiatest::Reporter* reporter, const SkBitmap::Config desiredConfig,
const bool success, const SkBitmap& src, const SkBitmap& dst,
- const bool deepCopy = true) {
+ const bool expectSameGenID) {
if (success) {
REPORTER_ASSERT(reporter, src.width() == dst.width());
REPORTER_ASSERT(reporter, src.height() == dst.height());
REPORTER_ASSERT(reporter, dst.config() == desiredConfig);
if (src.config() == dst.config()) {
- // FIXME: When calling copyTo (so deepCopy is false here), sometimes we copy the pixels
- // exactly, in which case the IDs should be the same, but sometimes we do a bitmap draw,
- // in which case the IDs should not be the same. Is there any way to determine which is
- // the case at this point?
- if (deepCopy) {
+ if (expectSameGenID) {
REPORTER_ASSERT(reporter, src.getGenerationID() == dst.getGenerationID());
+ } else {
+ REPORTER_ASSERT(reporter, src.getGenerationID() != dst.getGenerationID());
}
REPORTER_ASSERT(reporter, src.pixelRef() != NULL && dst.pixelRef() != NULL);
@@ -63,11 +61,17 @@ static void TestIndividualCopy(skiatest::Reporter* reporter, const SkBitmap::Con
SkBitmap srcReadBack, dstReadBack;
{
SkASSERT(src.getTexture() != NULL);
- bool readBack = src.pixelRef()->readPixels(&srcReadBack);
+ const SkIPoint origin = src.pixelRefOrigin();
+ const SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY,
+ src.width(), src.height());
+ bool readBack = src.pixelRef()->readPixels(&srcReadBack, &subset);
REPORTER_ASSERT(reporter, readBack);
}
if (dst.getTexture() != NULL) {
- bool readBack = dst.pixelRef()->readPixels(&dstReadBack);
+ const SkIPoint origin = dst.pixelRefOrigin();
+ const SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY,
+ dst.width(), dst.height());
+ bool readBack = dst.pixelRef()->readPixels(&dstReadBack, &subset);
REPORTER_ASSERT(reporter, readBack);
} else {
// If dst is not a texture, do a copy instead, to the same config as srcReadBack.
@@ -164,7 +168,7 @@ DEF_GPUTEST(GpuBitmapCopy, reporter, factory) {
boolStr(canSucceed));
}
- TestIndividualCopy(reporter, gPairs[j].fConfig, success, src, dst);
+ TestIndividualCopy(reporter, gPairs[j].fConfig, success, src, dst, true);
// Test copying the subset bitmap, using both copyTo and deepCopyTo.
if (extracted) {
@@ -173,7 +177,7 @@ DEF_GPUTEST(GpuBitmapCopy, reporter, factory) {
REPORTER_ASSERT(reporter, success == expected);
REPORTER_ASSERT(reporter, success == canSucceed);
TestIndividualCopy(reporter, gPairs[j].fConfig, success, subset, subsetCopy,
- false);
+ true);
// Reset the bitmap so that a failed copyTo will leave it in the expected state.
subsetCopy.reset();
@@ -182,6 +186,32 @@ DEF_GPUTEST(GpuBitmapCopy, reporter, factory) {
REPORTER_ASSERT(reporter, success == canSucceed);
TestIndividualCopy(reporter, gPairs[j].fConfig, success, subset, subsetCopy,
true);
+
+ // Now set a bitmap to be a subset that will share the same pixelref.
+ // This allows testing another case of cloning the genID. When calling copyTo
+ // on a bitmap representing a subset of its pixelref, the resulting pixelref
+ // should not share the genID, since we only copied the subset.
+ SkBitmap trueSubset;
+ // FIXME: Once https://codereview.chromium.org/109023008/ lands, call
+ // trueSubset.installPixelRef(src.pixelRef(), subset);
+ trueSubset.setConfig(gPairs[i].fConfig, W/2, H/2);
+ trueSubset.setPixelRef(src.pixelRef(), W/2, H/2);
+
+ subsetCopy.reset();
+ success = trueSubset.copyTo(&subsetCopy, gPairs[j].fConfig);
+ REPORTER_ASSERT(reporter, success == expected);
+ REPORTER_ASSERT(reporter, success == canSucceed);
+ TestIndividualCopy(reporter, gPairs[j].fConfig, success, trueSubset, subsetCopy,
+ false);
+
+ // deepCopyTo copies the entire pixelref, even if the bitmap only represents
+ // a subset. Therefore, the result should share the same genID.
+ subsetCopy.reset();
+ success = trueSubset.deepCopyTo(&subsetCopy, gPairs[j].fConfig);
+ REPORTER_ASSERT(reporter, success == expected);
+ REPORTER_ASSERT(reporter, success == canSucceed);
+ TestIndividualCopy(reporter, gPairs[j].fConfig, success, trueSubset, subsetCopy,
+ true);
}
} // for (size_t j = ...
} // for (size_t i = ...