aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests
diff options
context:
space:
mode:
authorGravatar kkinnunen <kkinnunen@nvidia.com>2015-11-17 22:53:28 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-11-17 22:53:28 -0800
commit4e18413b78236391f507875ab5d60aa14cb3c1a5 (patch)
treee203184a6e3a05193f53c0a5dcba24ae54e69588 /tests
parentcbf4fba43933302a846872e4c5ce8f1adb8b325e (diff)
Move SkImage tests from SurfaceTest to ImageTest
The general SkImage features seem to be tested in ImageTest instead of SurfaceTest. Helps in reviewing further reformatting of SurfaceTest. BUG=skia:2992 Review URL: https://codereview.chromium.org/1452123002
Diffstat (limited to 'tests')
-rw-r--r--tests/ImageTest.cpp430
-rw-r--r--tests/SurfaceTest.cpp427
2 files changed, 432 insertions, 425 deletions
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp
index 4768b8b0d4..d139ca7075 100644
--- a/tests/ImageTest.cpp
+++ b/tests/ImageTest.cpp
@@ -361,3 +361,433 @@ DEF_TEST(ImageFromIndex8Bitmap, r) {
SkAutoTUnref<SkImage> img(SkImage::NewFromBitmap(bm));
REPORTER_ASSERT(r, img.get() != nullptr);
}
+
+// TODO: The tests below were moved from SurfaceTests and should be reformatted.
+
+enum ImageType {
+ kRasterCopy_ImageType,
+ kRasterData_ImageType,
+ kRasterProc_ImageType,
+ kGpu_ImageType,
+ kCodec_ImageType,
+};
+
+#include "SkImageGenerator.h"
+
+class EmptyGenerator : public SkImageGenerator {
+public:
+ EmptyGenerator() : SkImageGenerator(SkImageInfo::MakeN32Premul(0, 0)) {}
+};
+
+static void test_empty_image(skiatest::Reporter* reporter) {
+ const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType);
+
+ REPORTER_ASSERT(reporter, nullptr == SkImage::NewRasterCopy(info, nullptr, 0));
+ REPORTER_ASSERT(reporter, nullptr == SkImage::NewRasterData(info, nullptr, 0));
+ REPORTER_ASSERT(reporter, nullptr == SkImage::NewFromRaster(info, nullptr, 0, nullptr, nullptr));
+ REPORTER_ASSERT(reporter, nullptr == SkImage::NewFromGenerator(new EmptyGenerator));
+}
+
+static void test_image(skiatest::Reporter* reporter) {
+ SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
+ size_t rowBytes = info.minRowBytes();
+ size_t size = info.getSafeSize(rowBytes);
+ SkData* data = SkData::NewUninitialized(size);
+
+ REPORTER_ASSERT(reporter, data->unique());
+ SkImage* image = SkImage::NewRasterData(info, data, rowBytes);
+ REPORTER_ASSERT(reporter, !data->unique());
+ image->unref();
+ REPORTER_ASSERT(reporter, data->unique());
+ data->unref();
+}
+
+// Want to ensure that our Release is called when the owning image is destroyed
+struct ReleaseDataContext {
+ skiatest::Reporter* fReporter;
+ SkData* fData;
+
+ static void Release(const void* pixels, void* context) {
+ ReleaseDataContext* state = (ReleaseDataContext*)context;
+ REPORTER_ASSERT(state->fReporter, state->fData);
+ state->fData->unref();
+ state->fData = nullptr;
+ }
+};
+
+// May we (soon) eliminate the need to keep testing this, by hiding the bloody device!
+#include "SkDevice.h"
+static uint32_t get_legacy_gen_id(SkSurface* surf) {
+ SkBaseDevice* device = surf->getCanvas()->getDevice_just_for_deprecated_compatibility_testing();
+ return device->accessBitmap(false).getGenerationID();
+}
+
+/*
+ * Test legacy behavor of bumping the surface's device's bitmap's genID when we access its
+ * texture handle for writing.
+ *
+ * Note: this needs to be tested separately from checking newImageSnapshot, as calling that
+ * can also incidentally bump the genID (when a new backing surface is created).
+ */
+template <class F>
+static void test_texture_handle_genID(skiatest::Reporter* reporter, SkSurface* surf, F f) {
+ const uint32_t gen0 = get_legacy_gen_id(surf);
+ f(surf, SkSurface::kFlushRead_BackendHandleAccess);
+ const uint32_t gen1 = get_legacy_gen_id(surf);
+ REPORTER_ASSERT(reporter, gen0 == gen1);
+
+ f(surf, SkSurface::kFlushWrite_BackendHandleAccess);
+ const uint32_t gen2 = get_legacy_gen_id(surf);
+ REPORTER_ASSERT(reporter, gen0 != gen2);
+
+ f(surf, SkSurface::kDiscardWrite_BackendHandleAccess);
+ const uint32_t gen3 = get_legacy_gen_id(surf);
+ REPORTER_ASSERT(reporter, gen0 != gen3);
+ REPORTER_ASSERT(reporter, gen2 != gen3);
+}
+
+template <class F>
+static void test_backend_handle(skiatest::Reporter* reporter, SkSurface* surf, F f) {
+ SkAutoTUnref<SkImage> image0(surf->newImageSnapshot());
+ GrBackendObject obj = f(surf, SkSurface::kFlushRead_BackendHandleAccess);
+ REPORTER_ASSERT(reporter, obj != 0);
+ SkAutoTUnref<SkImage> image1(surf->newImageSnapshot());
+ // just read access should not affect the snapshot
+ REPORTER_ASSERT(reporter, image0->uniqueID() == image1->uniqueID());
+
+ obj = f(surf, SkSurface::kFlushWrite_BackendHandleAccess);
+ REPORTER_ASSERT(reporter, obj != 0);
+ SkAutoTUnref<SkImage> image2(surf->newImageSnapshot());
+ // expect a new image, since we claimed we would write
+ REPORTER_ASSERT(reporter, image0->uniqueID() != image2->uniqueID());
+
+ obj = f(surf, SkSurface::kDiscardWrite_BackendHandleAccess);
+ REPORTER_ASSERT(reporter, obj != 0);
+ SkAutoTUnref<SkImage> image3(surf->newImageSnapshot());
+ // expect a new(er) image, since we claimed we would write
+ REPORTER_ASSERT(reporter, image0->uniqueID() != image3->uniqueID());
+ REPORTER_ASSERT(reporter, image2->uniqueID() != image3->uniqueID());
+}
+
+static SkImage* create_image(skiatest::Reporter* reporter,
+ ImageType imageType, GrContext* context, SkColor color,
+ ReleaseDataContext* releaseContext) {
+ const SkPMColor pmcolor = SkPreMultiplyColor(color);
+ const SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10);
+ const size_t rowBytes = info.minRowBytes();
+ const size_t size = rowBytes * info.height();
+
+ SkAutoTUnref<SkData> data(SkData::NewUninitialized(size));
+ void* addr = data->writable_data();
+ sk_memset32((SkPMColor*)addr, pmcolor, SkToInt(size >> 2));
+
+ switch (imageType) {
+ case kRasterCopy_ImageType:
+ return SkImage::NewRasterCopy(info, addr, rowBytes);
+ case kRasterData_ImageType:
+ return SkImage::NewRasterData(info, data, rowBytes);
+ case kRasterProc_ImageType:
+ SkASSERT(releaseContext);
+ releaseContext->fData = SkRef(data.get());
+ return SkImage::NewFromRaster(info, addr, rowBytes,
+ ReleaseDataContext::Release, releaseContext);
+ case kGpu_ImageType: {
+ SkAutoTUnref<SkSurface> surf(
+ SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted, info, 0));
+ surf->getCanvas()->clear(color);
+ // test our backing texture / rendertarget while were here...
+ auto textureAccessorFunc =
+ [](SkSurface* surf, SkSurface::BackendHandleAccess access) -> GrBackendObject {
+ return surf->getTextureHandle(access); };
+ auto renderTargetAccessorFunc =
+ [](SkSurface* surf, SkSurface::BackendHandleAccess access) -> GrBackendObject {
+ GrBackendObject obj;
+ SkAssertResult(surf->getRenderTargetHandle(&obj, access));
+ return obj; };
+ test_backend_handle(reporter, surf, textureAccessorFunc);
+ test_backend_handle(reporter, surf, renderTargetAccessorFunc);
+ test_texture_handle_genID(reporter, surf, textureAccessorFunc);
+ test_texture_handle_genID(reporter, surf, renderTargetAccessorFunc);
+
+ // redraw so our returned image looks as expected.
+ surf->getCanvas()->clear(color);
+ return surf->newImageSnapshot();
+ }
+ case kCodec_ImageType: {
+ SkBitmap bitmap;
+ bitmap.installPixels(info, addr, rowBytes);
+ SkAutoTUnref<SkData> src(
+ SkImageEncoder::EncodeData(bitmap, SkImageEncoder::kPNG_Type, 100));
+ return SkImage::NewFromEncoded(src);
+ }
+ }
+ SkASSERT(false);
+ return nullptr;
+}
+
+static void set_pixels(SkPMColor pixels[], int count, SkPMColor color) {
+ sk_memset32(pixels, color, count);
+}
+static bool has_pixels(const SkPMColor pixels[], int count, SkPMColor expected) {
+ for (int i = 0; i < count; ++i) {
+ if (pixels[i] != expected) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static void test_image_readpixels(skiatest::Reporter* reporter, SkImage* image,
+ SkPMColor expected) {
+ const SkPMColor notExpected = ~expected;
+
+ const int w = 2, h = 2;
+ const size_t rowBytes = w * sizeof(SkPMColor);
+ SkPMColor pixels[w*h];
+
+ SkImageInfo info;
+
+ info = SkImageInfo::MakeUnknown(w, h);
+ REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, 0, 0));
+
+ // out-of-bounds should fail
+ info = SkImageInfo::MakeN32Premul(w, h);
+ REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, -w, 0));
+ REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, 0, -h));
+ REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, image->width(), 0));
+ REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, 0, image->height()));
+
+ // top-left should succeed
+ set_pixels(pixels, w*h, notExpected);
+ REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes, 0, 0));
+ REPORTER_ASSERT(reporter, has_pixels(pixels, w*h, expected));
+
+ // bottom-right should succeed
+ set_pixels(pixels, w*h, notExpected);
+ REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes,
+ image->width() - w, image->height() - h));
+ REPORTER_ASSERT(reporter, has_pixels(pixels, w*h, expected));
+
+ // partial top-left should succeed
+ set_pixels(pixels, w*h, notExpected);
+ REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes, -1, -1));
+ REPORTER_ASSERT(reporter, pixels[3] == expected);
+ REPORTER_ASSERT(reporter, has_pixels(pixels, w*h - 1, notExpected));
+
+ // partial bottom-right should succeed
+ set_pixels(pixels, w*h, notExpected);
+ REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes,
+ image->width() - 1, image->height() - 1));
+ REPORTER_ASSERT(reporter, pixels[0] == expected);
+ REPORTER_ASSERT(reporter, has_pixels(&pixels[1], w*h - 1, notExpected));
+}
+
+static void check_legacy_bitmap(skiatest::Reporter* reporter, const SkImage* image,
+ const SkBitmap& bitmap, SkImage::LegacyBitmapMode mode) {
+ REPORTER_ASSERT(reporter, image->width() == bitmap.width());
+ REPORTER_ASSERT(reporter, image->height() == bitmap.height());
+ REPORTER_ASSERT(reporter, image->isOpaque() == bitmap.isOpaque());
+
+ if (SkImage::kRO_LegacyBitmapMode == mode) {
+ REPORTER_ASSERT(reporter, bitmap.isImmutable());
+ }
+
+ SkAutoLockPixels alp(bitmap);
+ REPORTER_ASSERT(reporter, bitmap.getPixels());
+
+ const SkImageInfo info = SkImageInfo::MakeN32(1, 1, bitmap.alphaType());
+ SkPMColor imageColor;
+ REPORTER_ASSERT(reporter, image->readPixels(info, &imageColor, sizeof(SkPMColor), 0, 0));
+ REPORTER_ASSERT(reporter, imageColor == *bitmap.getAddr32(0, 0));
+}
+
+static void test_legacy_bitmap(skiatest::Reporter* reporter, const SkImage* image) {
+ const SkImage::LegacyBitmapMode modes[] = {
+ SkImage::kRO_LegacyBitmapMode,
+ SkImage::kRW_LegacyBitmapMode,
+ };
+ for (size_t i = 0; i < SK_ARRAY_COUNT(modes); ++i) {
+ SkBitmap bitmap;
+ REPORTER_ASSERT(reporter, image->asLegacyBitmap(&bitmap, modes[i]));
+ check_legacy_bitmap(reporter, image, bitmap, modes[i]);
+
+ // Test subsetting to exercise the rowBytes logic.
+ SkBitmap tmp;
+ REPORTER_ASSERT(reporter, bitmap.extractSubset(&tmp, SkIRect::MakeWH(image->width() / 2,
+ image->height() / 2)));
+ SkAutoTUnref<SkImage> subsetImage(SkImage::NewFromBitmap(tmp));
+ REPORTER_ASSERT(reporter, subsetImage);
+
+ SkBitmap subsetBitmap;
+ REPORTER_ASSERT(reporter, subsetImage->asLegacyBitmap(&subsetBitmap, modes[i]));
+ check_legacy_bitmap(reporter, subsetImage, subsetBitmap, modes[i]);
+ }
+}
+
+static void test_imagepeek(skiatest::Reporter* reporter, GrContextFactory* factory) {
+ static const struct {
+ ImageType fType;
+ bool fPeekShouldSucceed;
+ const char* fName;
+ } gRec[] = {
+ { kRasterCopy_ImageType, true, "RasterCopy" },
+ { kRasterData_ImageType, true, "RasterData" },
+ { kRasterProc_ImageType, true, "RasterProc" },
+ { kGpu_ImageType, false, "Gpu" },
+ { kCodec_ImageType, false, "Codec" },
+ };
+
+ const SkColor color = SK_ColorRED;
+ const SkPMColor pmcolor = SkPreMultiplyColor(color);
+
+ GrContext* ctx = nullptr;
+#if SK_SUPPORT_GPU
+ ctx = factory->get(GrContextFactory::kNative_GLContextType);
+ if (nullptr == ctx) {
+ return;
+ }
+#endif
+
+ ReleaseDataContext releaseCtx;
+ releaseCtx.fReporter = reporter;
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) {
+ SkImageInfo info;
+ size_t rowBytes;
+
+ releaseCtx.fData = nullptr;
+ SkAutoTUnref<SkImage> image(create_image(reporter, gRec[i].fType, ctx, color, &releaseCtx));
+ if (!image.get()) {
+ SkDebugf("failed to createImage[%d] %s\n", i, gRec[i].fName);
+ continue; // gpu may not be enabled
+ }
+ if (kRasterProc_ImageType == gRec[i].fType) {
+ REPORTER_ASSERT(reporter, nullptr != releaseCtx.fData); // we are tracking the data
+ } else {
+ REPORTER_ASSERT(reporter, nullptr == releaseCtx.fData); // we ignored the context
+ }
+
+ test_legacy_bitmap(reporter, image);
+
+ const void* addr = image->peekPixels(&info, &rowBytes);
+ bool success = SkToBool(addr);
+ REPORTER_ASSERT(reporter, gRec[i].fPeekShouldSucceed == success);
+ if (success) {
+ REPORTER_ASSERT(reporter, 10 == info.width());
+ REPORTER_ASSERT(reporter, 10 == info.height());
+ REPORTER_ASSERT(reporter, kN32_SkColorType == info.colorType());
+ REPORTER_ASSERT(reporter, kPremul_SkAlphaType == info.alphaType() ||
+ kOpaque_SkAlphaType == info.alphaType());
+ REPORTER_ASSERT(reporter, info.minRowBytes() <= rowBytes);
+ REPORTER_ASSERT(reporter, pmcolor == *(const SkPMColor*)addr);
+ }
+
+ test_image_readpixels(reporter, image, pmcolor);
+ }
+ REPORTER_ASSERT(reporter, nullptr == releaseCtx.fData); // we released the data
+}
+#if SK_SUPPORT_GPU
+
+struct ReleaseTextureContext {
+ ReleaseTextureContext(skiatest::Reporter* reporter) {
+ fReporter = reporter;
+ fIsReleased = false;
+ }
+
+ skiatest::Reporter* fReporter;
+ bool fIsReleased;
+
+ void doRelease() {
+ REPORTER_ASSERT(fReporter, false == fIsReleased);
+ fIsReleased = true;
+ }
+
+ static void ReleaseProc(void* context) {
+ ((ReleaseTextureContext*)context)->doRelease();
+ }
+};
+
+static SkImage* make_desc_image(GrContext* ctx, int w, int h, GrBackendObject texID,
+ ReleaseTextureContext* releaseContext) {
+ GrBackendTextureDesc desc;
+ desc.fConfig = kSkia8888_GrPixelConfig;
+ // need to be a rendertarget for now...
+ desc.fFlags = kRenderTarget_GrBackendTextureFlag;
+ desc.fWidth = w;
+ desc.fHeight = h;
+ desc.fSampleCnt = 0;
+ desc.fTextureHandle = texID;
+ return releaseContext
+ ? SkImage::NewFromTexture(ctx, desc, kPremul_SkAlphaType,
+ ReleaseTextureContext::ReleaseProc, releaseContext)
+ : SkImage::NewFromTextureCopy(ctx, desc, kPremul_SkAlphaType);
+}
+
+static void test_image_color(skiatest::Reporter* reporter, SkImage* image, SkPMColor expected) {
+ const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
+ SkPMColor pixel;
+ REPORTER_ASSERT(reporter, image->readPixels(info, &pixel, sizeof(pixel), 0, 0));
+ REPORTER_ASSERT(reporter, pixel == expected);
+}
+
+DEF_GPUTEST(SkImage_NewFromTexture, reporter, factory) {
+ GrContext* ctx = factory->get(GrContextFactory::kNative_GLContextType);
+ if (!ctx) {
+ REPORTER_ASSERT(reporter, false);
+ return;
+ }
+ GrTextureProvider* provider = ctx->textureProvider();
+
+ const int w = 10;
+ const int h = 10;
+ SkPMColor storage[w * h];
+ const SkPMColor expected0 = SkPreMultiplyColor(SK_ColorRED);
+ sk_memset32(storage, expected0, w * h);
+
+ GrSurfaceDesc desc;
+ desc.fFlags = kRenderTarget_GrSurfaceFlag; // needs to be a rendertarget for readpixels();
+ desc.fOrigin = kDefault_GrSurfaceOrigin;
+ desc.fWidth = w;
+ desc.fHeight = h;
+ desc.fConfig = kSkia8888_GrPixelConfig;
+ desc.fSampleCnt = 0;
+
+ SkAutoTUnref<GrTexture> tex(provider->createTexture(desc, false, storage, w * 4));
+ if (!tex) {
+ REPORTER_ASSERT(reporter, false);
+ return;
+ }
+
+ GrBackendObject srcTex = tex->getTextureHandle();
+ ReleaseTextureContext releaseCtx(reporter);
+
+ SkAutoTUnref<SkImage> refImg(make_desc_image(ctx, w, h, srcTex, &releaseCtx));
+ SkAutoTUnref<SkImage> cpyImg(make_desc_image(ctx, w, h, srcTex, nullptr));
+
+ test_image_color(reporter, refImg, expected0);
+ test_image_color(reporter, cpyImg, expected0);
+
+ // Now lets jam new colors into our "external" texture, and see if the images notice
+ const SkPMColor expected1 = SkPreMultiplyColor(SK_ColorBLUE);
+ sk_memset32(storage, expected1, w * h);
+ tex->writePixels(0, 0, w, h, kSkia8888_GrPixelConfig, storage, GrContext::kFlushWrites_PixelOp);
+
+ // The cpy'd one should still see the old color
+#if 0
+ // There is no guarantee that refImg sees the new color. We are free to have made a copy. Our
+ // write pixels call violated the contract with refImg and refImg is now undefined.
+ test_image_color(reporter, refImg, expected1);
+#endif
+ test_image_color(reporter, cpyImg, expected0);
+
+ // Now exercise the release proc
+ REPORTER_ASSERT(reporter, !releaseCtx.fIsReleased);
+ refImg.reset(nullptr); // force a release of the image
+ REPORTER_ASSERT(reporter, releaseCtx.fIsReleased);
+}
+#endif
+DEF_GPUTEST(ImageTestsFromSurfaceTestsTODO, reporter, factory) {
+ test_image(reporter);
+ test_empty_image(reporter);
+ test_imagepeek(reporter, factory);
+}
diff --git a/tests/SurfaceTest.cpp b/tests/SurfaceTest.cpp
index a6739e3308..7e07e17f89 100644
--- a/tests/SurfaceTest.cpp
+++ b/tests/SurfaceTest.cpp
@@ -65,30 +65,6 @@ static SkSurface* create_surface(SurfaceType surfaceType, GrContext* context,
return nullptr;
}
-enum ImageType {
- kRasterCopy_ImageType,
- kRasterData_ImageType,
- kRasterProc_ImageType,
- kGpu_ImageType,
- kCodec_ImageType,
-};
-
-#include "SkImageGenerator.h"
-
-class EmptyGenerator : public SkImageGenerator {
-public:
- EmptyGenerator() : SkImageGenerator(SkImageInfo::MakeN32Premul(0, 0)) {}
-};
-
-static void test_empty_image(skiatest::Reporter* reporter) {
- const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType);
-
- REPORTER_ASSERT(reporter, nullptr == SkImage::NewRasterCopy(info, nullptr, 0));
- REPORTER_ASSERT(reporter, nullptr == SkImage::NewRasterData(info, nullptr, 0));
- REPORTER_ASSERT(reporter, nullptr == SkImage::NewFromRaster(info, nullptr, 0, nullptr, nullptr));
- REPORTER_ASSERT(reporter, nullptr == SkImage::NewFromGenerator(new EmptyGenerator));
-}
-
static void test_empty_surface(skiatest::Reporter* reporter, GrContext* ctx) {
const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType);
@@ -175,304 +151,6 @@ static void test_wrapped_texture_surface(skiatest::Reporter* reporter, GrContext
#endif
-static void test_image(skiatest::Reporter* reporter) {
- SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
- size_t rowBytes = info.minRowBytes();
- size_t size = info.getSafeSize(rowBytes);
- SkData* data = SkData::NewUninitialized(size);
-
- REPORTER_ASSERT(reporter, data->unique());
- SkImage* image = SkImage::NewRasterData(info, data, rowBytes);
- REPORTER_ASSERT(reporter, !data->unique());
- image->unref();
- REPORTER_ASSERT(reporter, data->unique());
- data->unref();
-}
-
-// Want to ensure that our Release is called when the owning image is destroyed
-struct ReleaseDataContext {
- skiatest::Reporter* fReporter;
- SkData* fData;
-
- static void Release(const void* pixels, void* context) {
- ReleaseDataContext* state = (ReleaseDataContext*)context;
- REPORTER_ASSERT(state->fReporter, state->fData);
- state->fData->unref();
- state->fData = nullptr;
- }
-};
-
-// May we (soon) eliminate the need to keep testing this, by hiding the bloody device!
-#include "SkDevice.h"
-static uint32_t get_legacy_gen_id(SkSurface* surf) {
- SkBaseDevice* device = surf->getCanvas()->getDevice_just_for_deprecated_compatibility_testing();
- return device->accessBitmap(false).getGenerationID();
-}
-
-/*
- * Test legacy behavor of bumping the surface's device's bitmap's genID when we access its
- * texture handle for writing.
- *
- * Note: this needs to be tested separately from checking newImageSnapshot, as calling that
- * can also incidentally bump the genID (when a new backing surface is created).
- */
-template <class F>
-static void test_texture_handle_genID(skiatest::Reporter* reporter, SkSurface* surf, F f) {
- const uint32_t gen0 = get_legacy_gen_id(surf);
- f(surf, SkSurface::kFlushRead_BackendHandleAccess);
- const uint32_t gen1 = get_legacy_gen_id(surf);
- REPORTER_ASSERT(reporter, gen0 == gen1);
-
- f(surf, SkSurface::kFlushWrite_BackendHandleAccess);
- const uint32_t gen2 = get_legacy_gen_id(surf);
- REPORTER_ASSERT(reporter, gen0 != gen2);
-
- f(surf, SkSurface::kDiscardWrite_BackendHandleAccess);
- const uint32_t gen3 = get_legacy_gen_id(surf);
- REPORTER_ASSERT(reporter, gen0 != gen3);
- REPORTER_ASSERT(reporter, gen2 != gen3);
-}
-
-template <class F>
-static void test_backend_handle(skiatest::Reporter* reporter, SkSurface* surf, F f) {
- SkAutoTUnref<SkImage> image0(surf->newImageSnapshot());
- GrBackendObject obj = f(surf, SkSurface::kFlushRead_BackendHandleAccess);
- REPORTER_ASSERT(reporter, obj != 0);
- SkAutoTUnref<SkImage> image1(surf->newImageSnapshot());
- // just read access should not affect the snapshot
- REPORTER_ASSERT(reporter, image0->uniqueID() == image1->uniqueID());
-
- obj = f(surf, SkSurface::kFlushWrite_BackendHandleAccess);
- REPORTER_ASSERT(reporter, obj != 0);
- SkAutoTUnref<SkImage> image2(surf->newImageSnapshot());
- // expect a new image, since we claimed we would write
- REPORTER_ASSERT(reporter, image0->uniqueID() != image2->uniqueID());
-
- obj = f(surf, SkSurface::kDiscardWrite_BackendHandleAccess);
- REPORTER_ASSERT(reporter, obj != 0);
- SkAutoTUnref<SkImage> image3(surf->newImageSnapshot());
- // expect a new(er) image, since we claimed we would write
- REPORTER_ASSERT(reporter, image0->uniqueID() != image3->uniqueID());
- REPORTER_ASSERT(reporter, image2->uniqueID() != image3->uniqueID());
-}
-
-static SkImage* create_image(skiatest::Reporter* reporter,
- ImageType imageType, GrContext* context, SkColor color,
- ReleaseDataContext* releaseContext) {
- const SkPMColor pmcolor = SkPreMultiplyColor(color);
- const SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10);
- const size_t rowBytes = info.minRowBytes();
- const size_t size = rowBytes * info.height();
-
- SkAutoTUnref<SkData> data(SkData::NewUninitialized(size));
- void* addr = data->writable_data();
- sk_memset32((SkPMColor*)addr, pmcolor, SkToInt(size >> 2));
-
- switch (imageType) {
- case kRasterCopy_ImageType:
- return SkImage::NewRasterCopy(info, addr, rowBytes);
- case kRasterData_ImageType:
- return SkImage::NewRasterData(info, data, rowBytes);
- case kRasterProc_ImageType:
- SkASSERT(releaseContext);
- releaseContext->fData = SkRef(data.get());
- return SkImage::NewFromRaster(info, addr, rowBytes,
- ReleaseDataContext::Release, releaseContext);
- case kGpu_ImageType: {
- SkAutoTUnref<SkSurface> surf(
- SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted, info, 0));
- surf->getCanvas()->clear(color);
- // test our backing texture / rendertarget while were here...
- auto textureAccessorFunc =
- [](SkSurface* surf, SkSurface::BackendHandleAccess access) -> GrBackendObject {
- return surf->getTextureHandle(access); };
- auto renderTargetAccessorFunc =
- [](SkSurface* surf, SkSurface::BackendHandleAccess access) -> GrBackendObject {
- GrBackendObject obj;
- SkAssertResult(surf->getRenderTargetHandle(&obj, access));
- return obj; };
- test_backend_handle(reporter, surf, textureAccessorFunc);
- test_backend_handle(reporter, surf, renderTargetAccessorFunc);
- test_texture_handle_genID(reporter, surf, textureAccessorFunc);
- test_texture_handle_genID(reporter, surf, renderTargetAccessorFunc);
-
- // redraw so our returned image looks as expected.
- surf->getCanvas()->clear(color);
- return surf->newImageSnapshot();
- }
- case kCodec_ImageType: {
- SkBitmap bitmap;
- bitmap.installPixels(info, addr, rowBytes);
- SkAutoTUnref<SkData> src(
- SkImageEncoder::EncodeData(bitmap, SkImageEncoder::kPNG_Type, 100));
- return SkImage::NewFromEncoded(src);
- }
- }
- SkASSERT(false);
- return nullptr;
-}
-
-static void set_pixels(SkPMColor pixels[], int count, SkPMColor color) {
- sk_memset32(pixels, color, count);
-}
-static bool has_pixels(const SkPMColor pixels[], int count, SkPMColor expected) {
- for (int i = 0; i < count; ++i) {
- if (pixels[i] != expected) {
- return false;
- }
- }
- return true;
-}
-
-static void test_image_readpixels(skiatest::Reporter* reporter, SkImage* image,
- SkPMColor expected) {
- const SkPMColor notExpected = ~expected;
-
- const int w = 2, h = 2;
- const size_t rowBytes = w * sizeof(SkPMColor);
- SkPMColor pixels[w*h];
-
- SkImageInfo info;
-
- info = SkImageInfo::MakeUnknown(w, h);
- REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, 0, 0));
-
- // out-of-bounds should fail
- info = SkImageInfo::MakeN32Premul(w, h);
- REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, -w, 0));
- REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, 0, -h));
- REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, image->width(), 0));
- REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, 0, image->height()));
-
- // top-left should succeed
- set_pixels(pixels, w*h, notExpected);
- REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes, 0, 0));
- REPORTER_ASSERT(reporter, has_pixels(pixels, w*h, expected));
-
- // bottom-right should succeed
- set_pixels(pixels, w*h, notExpected);
- REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes,
- image->width() - w, image->height() - h));
- REPORTER_ASSERT(reporter, has_pixels(pixels, w*h, expected));
-
- // partial top-left should succeed
- set_pixels(pixels, w*h, notExpected);
- REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes, -1, -1));
- REPORTER_ASSERT(reporter, pixels[3] == expected);
- REPORTER_ASSERT(reporter, has_pixels(pixels, w*h - 1, notExpected));
-
- // partial bottom-right should succeed
- set_pixels(pixels, w*h, notExpected);
- REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes,
- image->width() - 1, image->height() - 1));
- REPORTER_ASSERT(reporter, pixels[0] == expected);
- REPORTER_ASSERT(reporter, has_pixels(&pixels[1], w*h - 1, notExpected));
-}
-
-static void check_legacy_bitmap(skiatest::Reporter* reporter, const SkImage* image,
- const SkBitmap& bitmap, SkImage::LegacyBitmapMode mode) {
- REPORTER_ASSERT(reporter, image->width() == bitmap.width());
- REPORTER_ASSERT(reporter, image->height() == bitmap.height());
- REPORTER_ASSERT(reporter, image->isOpaque() == bitmap.isOpaque());
-
- if (SkImage::kRO_LegacyBitmapMode == mode) {
- REPORTER_ASSERT(reporter, bitmap.isImmutable());
- }
-
- SkAutoLockPixels alp(bitmap);
- REPORTER_ASSERT(reporter, bitmap.getPixels());
-
- const SkImageInfo info = SkImageInfo::MakeN32(1, 1, bitmap.alphaType());
- SkPMColor imageColor;
- REPORTER_ASSERT(reporter, image->readPixels(info, &imageColor, sizeof(SkPMColor), 0, 0));
- REPORTER_ASSERT(reporter, imageColor == *bitmap.getAddr32(0, 0));
-}
-
-static void test_legacy_bitmap(skiatest::Reporter* reporter, const SkImage* image) {
- const SkImage::LegacyBitmapMode modes[] = {
- SkImage::kRO_LegacyBitmapMode,
- SkImage::kRW_LegacyBitmapMode,
- };
- for (size_t i = 0; i < SK_ARRAY_COUNT(modes); ++i) {
- SkBitmap bitmap;
- REPORTER_ASSERT(reporter, image->asLegacyBitmap(&bitmap, modes[i]));
- check_legacy_bitmap(reporter, image, bitmap, modes[i]);
-
- // Test subsetting to exercise the rowBytes logic.
- SkBitmap tmp;
- REPORTER_ASSERT(reporter, bitmap.extractSubset(&tmp, SkIRect::MakeWH(image->width() / 2,
- image->height() / 2)));
- SkAutoTUnref<SkImage> subsetImage(SkImage::NewFromBitmap(tmp));
- REPORTER_ASSERT(reporter, subsetImage);
-
- SkBitmap subsetBitmap;
- REPORTER_ASSERT(reporter, subsetImage->asLegacyBitmap(&subsetBitmap, modes[i]));
- check_legacy_bitmap(reporter, subsetImage, subsetBitmap, modes[i]);
- }
-}
-
-static void test_imagepeek(skiatest::Reporter* reporter, GrContextFactory* factory) {
- static const struct {
- ImageType fType;
- bool fPeekShouldSucceed;
- const char* fName;
- } gRec[] = {
- { kRasterCopy_ImageType, true, "RasterCopy" },
- { kRasterData_ImageType, true, "RasterData" },
- { kRasterProc_ImageType, true, "RasterProc" },
- { kGpu_ImageType, false, "Gpu" },
- { kCodec_ImageType, false, "Codec" },
- };
-
- const SkColor color = SK_ColorRED;
- const SkPMColor pmcolor = SkPreMultiplyColor(color);
-
- GrContext* ctx = nullptr;
-#if SK_SUPPORT_GPU
- ctx = factory->get(GrContextFactory::kNative_GLContextType);
- if (nullptr == ctx) {
- return;
- }
-#endif
-
- ReleaseDataContext releaseCtx;
- releaseCtx.fReporter = reporter;
-
- for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) {
- SkImageInfo info;
- size_t rowBytes;
-
- releaseCtx.fData = nullptr;
- SkAutoTUnref<SkImage> image(create_image(reporter, gRec[i].fType, ctx, color, &releaseCtx));
- if (!image.get()) {
- SkDebugf("failed to createImage[%d] %s\n", i, gRec[i].fName);
- continue; // gpu may not be enabled
- }
- if (kRasterProc_ImageType == gRec[i].fType) {
- REPORTER_ASSERT(reporter, nullptr != releaseCtx.fData); // we are tracking the data
- } else {
- REPORTER_ASSERT(reporter, nullptr == releaseCtx.fData); // we ignored the context
- }
-
- test_legacy_bitmap(reporter, image);
-
- const void* addr = image->peekPixels(&info, &rowBytes);
- bool success = SkToBool(addr);
- REPORTER_ASSERT(reporter, gRec[i].fPeekShouldSucceed == success);
- if (success) {
- REPORTER_ASSERT(reporter, 10 == info.width());
- REPORTER_ASSERT(reporter, 10 == info.height());
- REPORTER_ASSERT(reporter, kN32_SkColorType == info.colorType());
- REPORTER_ASSERT(reporter, kPremul_SkAlphaType == info.alphaType() ||
- kOpaque_SkAlphaType == info.alphaType());
- REPORTER_ASSERT(reporter, info.minRowBytes() <= rowBytes);
- REPORTER_ASSERT(reporter, pmcolor == *(const SkPMColor*)addr);
- }
-
- test_image_readpixels(reporter, image, pmcolor);
- }
- REPORTER_ASSERT(reporter, nullptr == releaseCtx.fData); // we released the data
-}
static void test_canvaspeek(skiatest::Reporter* reporter,
GrContextFactory* factory) {
@@ -883,17 +561,15 @@ static void TestSurfaceNoCanvas(skiatest::Reporter* reporter,
}
DEF_GPUTEST(Surface, reporter, factory) {
- test_image(reporter);
-
TestSurfaceCopyOnWrite(reporter, kRaster_SurfaceType, nullptr);
TestSurfaceWritableAfterSnapshotRelease(reporter, kRaster_SurfaceType, nullptr);
TestSurfaceNoCanvas(reporter, kRaster_SurfaceType, nullptr, SkSurface::kDiscard_ContentChangeMode);
TestSurfaceNoCanvas(reporter, kRaster_SurfaceType, nullptr, SkSurface::kRetain_ContentChangeMode);
- test_empty_image(reporter);
+
test_empty_surface(reporter, nullptr);
- test_imagepeek(reporter, factory);
+
test_canvaspeek(reporter, factory);
test_accessPixels(reporter, factory);
@@ -931,103 +607,4 @@ DEF_GPUTEST(Surface, reporter, factory) {
#endif
}
-#if SK_SUPPORT_GPU
-
-struct ReleaseTextureContext {
- ReleaseTextureContext(skiatest::Reporter* reporter) {
- fReporter = reporter;
- fIsReleased = false;
- }
-
- skiatest::Reporter* fReporter;
- bool fIsReleased;
-
- void doRelease() {
- REPORTER_ASSERT(fReporter, false == fIsReleased);
- fIsReleased = true;
- }
-
- static void ReleaseProc(void* context) {
- ((ReleaseTextureContext*)context)->doRelease();
- }
-};
-
-static SkImage* make_desc_image(GrContext* ctx, int w, int h, GrBackendObject texID,
- ReleaseTextureContext* releaseContext) {
- GrBackendTextureDesc desc;
- desc.fConfig = kSkia8888_GrPixelConfig;
- // need to be a rendertarget for now...
- desc.fFlags = kRenderTarget_GrBackendTextureFlag;
- desc.fWidth = w;
- desc.fHeight = h;
- desc.fSampleCnt = 0;
- desc.fTextureHandle = texID;
- return releaseContext
- ? SkImage::NewFromTexture(ctx, desc, kPremul_SkAlphaType,
- ReleaseTextureContext::ReleaseProc, releaseContext)
- : SkImage::NewFromTextureCopy(ctx, desc, kPremul_SkAlphaType);
-}
-
-static void test_image_color(skiatest::Reporter* reporter, SkImage* image, SkPMColor expected) {
- const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
- SkPMColor pixel;
- REPORTER_ASSERT(reporter, image->readPixels(info, &pixel, sizeof(pixel), 0, 0));
- REPORTER_ASSERT(reporter, pixel == expected);
-}
-
-DEF_GPUTEST(SkImage_NewFromTexture, reporter, factory) {
- GrContext* ctx = factory->get(GrContextFactory::kNative_GLContextType);
- if (!ctx) {
- REPORTER_ASSERT(reporter, false);
- return;
- }
- GrTextureProvider* provider = ctx->textureProvider();
-
- const int w = 10;
- const int h = 10;
- SkPMColor storage[w * h];
- const SkPMColor expected0 = SkPreMultiplyColor(SK_ColorRED);
- sk_memset32(storage, expected0, w * h);
-
- GrSurfaceDesc desc;
- desc.fFlags = kRenderTarget_GrSurfaceFlag; // needs to be a rendertarget for readpixels();
- desc.fOrigin = kDefault_GrSurfaceOrigin;
- desc.fWidth = w;
- desc.fHeight = h;
- desc.fConfig = kSkia8888_GrPixelConfig;
- desc.fSampleCnt = 0;
-
- SkAutoTUnref<GrTexture> tex(provider->createTexture(desc, false, storage, w * 4));
- if (!tex) {
- REPORTER_ASSERT(reporter, false);
- return;
- }
-
- GrBackendObject srcTex = tex->getTextureHandle();
- ReleaseTextureContext releaseCtx(reporter);
-
- SkAutoTUnref<SkImage> refImg(make_desc_image(ctx, w, h, srcTex, &releaseCtx));
- SkAutoTUnref<SkImage> cpyImg(make_desc_image(ctx, w, h, srcTex, nullptr));
- test_image_color(reporter, refImg, expected0);
- test_image_color(reporter, cpyImg, expected0);
-
- // Now lets jam new colors into our "external" texture, and see if the images notice
- const SkPMColor expected1 = SkPreMultiplyColor(SK_ColorBLUE);
- sk_memset32(storage, expected1, w * h);
- tex->writePixels(0, 0, w, h, kSkia8888_GrPixelConfig, storage, GrContext::kFlushWrites_PixelOp);
-
- // The cpy'd one should still see the old color
-#if 0
- // There is no guarantee that refImg sees the new color. We are free to have made a copy. Our
- // write pixels call violated the contract with refImg and refImg is now undefined.
- test_image_color(reporter, refImg, expected1);
-#endif
- test_image_color(reporter, cpyImg, expected0);
-
- // Now exercise the release proc
- REPORTER_ASSERT(reporter, !releaseCtx.fIsReleased);
- refImg.reset(nullptr); // force a release of the image
- REPORTER_ASSERT(reporter, releaseCtx.fIsReleased);
-}
-#endif