aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar robertphillips <robertphillips@google.com>2016-07-18 08:31:31 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-07-18 08:31:31 -0700
commit6451a0cea6007aff54565ec82e2f86cb1d32ecc7 (patch)
treec9643e2e2cfc4e8152be249ea5ab4716ed43825e
parentf023e6879c63e5d223e89707a714f18688a93a4a (diff)
Add makeSpecial calls to SkGpuDevice
-rw-r--r--include/core/SkDevice.h7
-rw-r--r--src/core/SkDevice.cpp15
-rw-r--r--src/gpu/SkGpuDevice.cpp44
-rw-r--r--src/gpu/SkGpuDevice.h8
-rw-r--r--tests/DeviceTest.cpp124
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