diff options
author | robertphillips <robertphillips@google.com> | 2016-07-18 08:31:31 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-07-18 08:31:31 -0700 |
commit | 6451a0cea6007aff54565ec82e2f86cb1d32ecc7 (patch) | |
tree | c9643e2e2cfc4e8152be249ea5ab4716ed43825e | |
parent | f023e6879c63e5d223e89707a714f18688a93a4a (diff) |
Add makeSpecial calls to SkGpuDevice
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2161533003
Review-Url: https://codereview.chromium.org/2161533003
-rw-r--r-- | include/core/SkDevice.h | 7 | ||||
-rw-r--r-- | src/core/SkDevice.cpp | 15 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 44 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.h | 8 | ||||
-rw-r--r-- | tests/DeviceTest.cpp | 124 |
5 files changed, 193 insertions, 5 deletions
diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h index e960003f9a..864f71225f 100644 --- a/include/core/SkDevice.h +++ b/include/core/SkDevice.h @@ -22,6 +22,7 @@ struct SkIRect; class SkMatrix; class SkMetaData; class SkRegion; +class SkSpecialImage; class GrRenderTarget; class SK_API SkBaseDevice : public SkRefCnt { @@ -276,6 +277,11 @@ protected: virtual void drawTextRSXform(const SkDraw&, const void* text, size_t len, const SkRSXform[], const SkPaint&); + virtual void drawSpecial(const SkDraw&, SkSpecialImage*, int x, int y, const SkPaint&); + virtual sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&); + virtual sk_sp<SkSpecialImage> makeSpecial(SkImage*); + virtual sk_sp<SkSpecialImage> snapSpecial(); + bool readPixels(const SkImageInfo&, void* dst, size_t rowBytes, int x, int y); /////////////////////////////////////////////////////////////////////////// @@ -369,6 +375,7 @@ private: friend class SkDeviceFilteredPaint; friend class SkNoPixelsBitmapDevice; friend class SkSurface_Raster; + friend class DeviceTestingAccess; // used to change the backend's pixels (and possibly config/rowbytes) // but cannot change the width/height, so there should be no change to diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp index 5c92703f31..7ecdbef095 100644 --- a/src/core/SkDevice.cpp +++ b/src/core/SkDevice.cpp @@ -23,6 +23,21 @@ #include "SkTextBlobRunIterator.h" #include "SkTextToPathIter.h" +void SkBaseDevice::drawSpecial(const SkDraw&, SkSpecialImage*, int x, int y, const SkPaint&) { +} + +sk_sp<SkSpecialImage> SkBaseDevice::makeSpecial(const SkBitmap&) { + return nullptr; +} + +sk_sp<SkSpecialImage> SkBaseDevice::makeSpecial(SkImage*) { + return nullptr; +} + +sk_sp<SkSpecialImage> SkBaseDevice::snapSpecial() { + return nullptr; +} + SkBaseDevice::SkBaseDevice(const SkSurfaceProps& surfaceProps) : fSurfaceProps(surfaceProps) #ifdef SK_DEBUG diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index e9baae54a8..e5d42cd811 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -1399,7 +1399,47 @@ void SkGpuDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap, this->drawTextureProducer(&maker, src, dst, constraint, *draw.fMatrix, fClip, paint); } -sk_sp<SkSpecialImage> SkGpuDevice::asSpecial() { +sk_sp<SkSpecialImage> SkGpuDevice::makeSpecial(const SkBitmap& bitmap) { + SkASSERT(!bitmap.getTexture()); + + SkAutoLockPixels alp(bitmap, true); + if (!bitmap.readyToDraw()) { + return nullptr; + } + + GrTexture* texture; + AutoBitmapTexture abt(fContext, bitmap, GrTextureParams::ClampNoFilter(), + SkSourceGammaTreatment::kRespect, &texture); + if (!texture) { + return nullptr; + } + + return SkSpecialImage::MakeFromGpu(bitmap.bounds(), + bitmap.getGenerationID(), + sk_ref_sp(texture), + &this->surfaceProps()); +} + +sk_sp<SkSpecialImage> SkGpuDevice::makeSpecial(SkImage* image) { + SkPixmap pm; + if (image->isTextureBacked()) { + GrTexture* texture = as_IB(image)->peekTexture(); + + return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(image->width(), image->height()), + image->uniqueID(), + sk_ref_sp(texture), + &this->surfaceProps()); + } else if (image->peekPixels(&pm)) { + SkBitmap bm; + + bm.installPixels(pm); + return this->makeSpecial(bm); + } else { + return nullptr; + } +} + +sk_sp<SkSpecialImage> SkGpuDevice::snapSpecial() { sk_sp<GrTexture> texture(this->accessDrawContext()->asTexture()); if (!texture) { // When the device doesn't have a texture, we create a temporary texture. @@ -1436,7 +1476,7 @@ void SkGpuDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device, CHECK_SHOULD_DRAW(draw); SkGpuDevice* dev = static_cast<SkGpuDevice*>(device); - sk_sp<SkSpecialImage> srcImg(dev->asSpecial()); + sk_sp<SkSpecialImage> srcImg(dev->snapSpecial()); if (!srcImg) { return; } diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h index 56d934fe7d..85764467cb 100644 --- a/src/gpu/SkGpuDevice.h +++ b/src/gpu/SkGpuDevice.h @@ -131,9 +131,11 @@ public: void drawBitmapNine(const SkDraw& draw, const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, const SkPaint& paint) override; - sk_sp<SkSpecialImage> asSpecial(); - void drawSpecial(const SkDraw& draw, SkSpecialImage*, - int left, int top, const SkPaint& paint); + void drawSpecial(const SkDraw&, SkSpecialImage*, + int left, int top, const SkPaint& paint) override; + sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&) override; + sk_sp<SkSpecialImage> makeSpecial(SkImage*) override; + sk_sp<SkSpecialImage> snapSpecial() override; void flush() override; diff --git a/tests/DeviceTest.cpp b/tests/DeviceTest.cpp new file mode 100644 index 0000000000..d6bd1bfe47 --- /dev/null +++ b/tests/DeviceTest.cpp @@ -0,0 +1,124 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkBitmapDevice.h" +#include "SkDevice.h" +#include "SkSpecialImage.h" + +#if SK_SUPPORT_GPU +#include "SkGpuDevice.h" +#endif + +#include "Test.h" + +class DeviceTestingAccess { +public: + static sk_sp<SkSpecialImage> MakeSpecial(SkBaseDevice* dev, const SkBitmap& bm) { + return dev->makeSpecial(bm); + } + + static sk_sp<SkSpecialImage> MakeSpecial(SkBaseDevice* dev, SkImage* img) { + return dev->makeSpecial(img); + } + + static sk_sp<SkSpecialImage> SnapSpecial(SkBaseDevice* dev) { + return dev->snapSpecial(); + } +}; + +// TODO: re-enable this when Raster methods are implemented +#if 0 +DEF_TEST(SpecialImage_BitmapDevice, reporter) { + static const int kWidth = 100; + static const int kHeight = 90; + + SkImageInfo ii = SkImageInfo::MakeN32Premul(2*kWidth, 2*kHeight); + + SkAutoTUnref<SkBaseDevice> bmDev(SkBitmapDevice::Create(ii)); + + SkBitmap bm; + bm.tryAllocN32Pixels(kWidth, kHeight); + + // Create a raster-backed special image from a raster-backed SkBitmap + sk_sp<SkSpecialImage> special = DeviceTestingAccess::MakeSpecial(bmDev.get(), bm); + SkASSERT(!special->isTextureBacked()); + SkASSERT(kWidth == special->width()); + SkASSERT(kHeight == special->height()); + SkASSERT(bm.getGenerationID() == special->uniqueID()); + SkASSERT(SkIRect::MakeWH(kWidth, kHeight) == special->subset()); + + // Create a raster-backed special image from a raster-backed SkImage + sk_sp<SkImage> image(SkImage::MakeFromBitmap(bm)); + special = DeviceTestingAccess::MakeSpecial(bmDev.get(), image.get()); + SkASSERT(!special->isTextureBacked()); + SkASSERT(kWidth == special->width()); + SkASSERT(kHeight == special->height()); + SkASSERT(bm.getGenerationID() == special->uniqueID()); + SkASSERT(SkIRect::MakeWH(kWidth, kHeight) == special->subset()); + + // Snap the device as a raster-backed special image + special = DeviceTestingAccess::SnapSpecial(bmDev.get()); + SkASSERT(!special->isTextureBacked()); + SkASSERT(2*kWidth == special->width()); + SkASSERT(2*kHeight == special->height()); + SkASSERT(SkIRect::MakeWH(2*kWidth, 2*kHeight) == special->subset()); +} +#endif + + +#if SK_SUPPORT_GPU + +DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SpecialImage_GPUDevice, reporter, ctxInfo) { + GrContext* context = ctxInfo.grContext(); + + static const int kWidth = 100; + static const int kHeight = 90; + + SkImageInfo ii = SkImageInfo::MakeN32Premul(2*kWidth, 2*kHeight); + + sk_sp<SkBaseDevice> gpuDev(SkGpuDevice::Make(context, SkBudgeted::kNo, ii, + 0, nullptr, SkGpuDevice::kClear_InitContents)); + + SkBitmap bm; + SkAssertResult(bm.tryAllocN32Pixels(kWidth, kHeight)); + + // Create a gpu-backed special image from a raster-backed SkBitmap + sk_sp<SkSpecialImage> special = DeviceTestingAccess::MakeSpecial(gpuDev.get(), bm); + SkASSERT(special->isTextureBacked()); + SkASSERT(kWidth == special->width()); + SkASSERT(kHeight == special->height()); + SkASSERT(bm.getGenerationID() == special->uniqueID()); + SkASSERT(SkIRect::MakeWH(kWidth, kHeight) == special->subset()); + + // Create a gpu-backed special image from a raster-backed SkImage + sk_sp<SkImage> image(SkImage::MakeFromBitmap(bm)); + special = DeviceTestingAccess::MakeSpecial(gpuDev.get(), image.get()); + SkASSERT(special->isTextureBacked()); + SkASSERT(kWidth == special->width()); + SkASSERT(kHeight == special->height()); + // TODO: Hmmm, this is a bit unexpected + SkASSERT(image->uniqueID() != special->uniqueID()); + SkASSERT(SkIRect::MakeWH(kWidth, kHeight) == special->subset()); + + // Create a gpu-backed special image from a gpu-backed SkImage + image = image->makeTextureImage(context); + special = DeviceTestingAccess::MakeSpecial(gpuDev.get(), image.get()); + SkASSERT(special->isTextureBacked()); + SkASSERT(kWidth == special->width()); + SkASSERT(kHeight == special->height()); + SkASSERT(image->uniqueID() == special->uniqueID()); + SkASSERT(SkIRect::MakeWH(kWidth, kHeight) == special->subset()); + + // Snap the device as a gpu-backed special image + special = DeviceTestingAccess::SnapSpecial(gpuDev.get()); + SkASSERT(special->isTextureBacked()); + SkASSERT(2*kWidth == special->width()); + SkASSERT(2*kHeight == special->height()); + SkASSERT(SkIRect::MakeWH(2*kWidth, 2*kHeight) == special->subset()); +} + +#endif |