aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Mike Reed <reed@google.com>2018-02-08 14:10:40 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-02-08 19:34:50 +0000
commit4c790bd7dd8a6edacfc39b65b7043742331ab4da (patch)
tree1d66da0bfa6b7627315388b0d3f712897ea03bbd
parentb9fc24e465767db8bd9dbddfd67c905392346e66 (diff)
add writePixels to SkSurface --> so we can remove it from canvas
Bug: skia: Change-Id: Ib35d7bdc113c3fd9f6dfacb42ec61aaa448cb165 Reviewed-on: https://skia-review.googlesource.com/105623 Commit-Queue: Mike Reed <reed@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
-rw-r--r--docs/SkSurface_Reference.bmh54
-rw-r--r--include/core/SkSurface.h13
-rw-r--r--src/image/SkSurface.cpp25
-rw-r--r--src/image/SkSurface_Base.h2
-rw-r--r--src/image/SkSurface_Gpu.cpp4
-rw-r--r--src/image/SkSurface_Gpu.h1
-rw-r--r--src/image/SkSurface_Raster.cpp5
-rw-r--r--tests/PremulAlphaRoundTripTest.cpp9
-rw-r--r--tests/WritePixelsTest.cpp34
-rw-r--r--tools/sk_tool_utils.cpp6
-rw-r--r--tools/sk_tool_utils.h3
11 files changed, 124 insertions, 32 deletions
diff --git a/docs/SkSurface_Reference.bmh b/docs/SkSurface_Reference.bmh
index 189ff79e9a..7935bfe563 100644
--- a/docs/SkSurface_Reference.bmh
+++ b/docs/SkSurface_Reference.bmh
@@ -1392,7 +1392,7 @@ pixmap contents become invalid on any future change to Surface.
}
##
-#SeeAlso readPixels
+#SeeAlso readPixels writePixels
#Method ##
@@ -1451,7 +1451,7 @@ Does not copy, and returns false if:
}
##
-#SeeAlso peekPixels
+#SeeAlso peekPixels writePixels
#Method ##
@@ -1517,7 +1517,7 @@ Does not copy, and returns false if:
canvas->drawImage(image, 0, 0);
##
-#SeeAlso peekPixels
+#SeeAlso peekPixels writePixels
#Method ##
@@ -1575,7 +1575,53 @@ Does not copy, and returns false if:
canvas->drawBitmap(bitmap, 0, 0);
##
-#SeeAlso peekPixels
+#SeeAlso peekPixels writePixels
+
+#Method ##
+
+# ------------------------------------------------------------------------------
+
+#Method void writePixels(const SkPixmap& src, int dstX, int dstY)
+
+Copies Rect of pixels from the src Pixmap to the Surface.
+
+Source Rect corners are (0, 0) and (src.width(), src.height()).
+Destination Rect corners are (dstX, dstY) and (dstX + Surface width(), dstY + Surface height()).
+Copies each readable pixel intersecting both rectangles, without scaling,
+converting to Surface colorType() and Surface alphaType() if required.
+
+#Param src storage for pixels to copy to Surface ##
+#Param dstX x position relative to Surface to begin copy; may be negative ##
+#Param dstY x position relative to Surface to begin copy; may be negative ##
+
+#Example
+ // todo
+##
+
+#SeeAlso readPixels peekPixels
+
+#Method ##
+
+# ------------------------------------------------------------------------------
+
+#Method void writePixels(const SkBitmap& src, int dstX, int dstY)
+
+Copies Rect of pixels from the src Bitmap to the Surface.
+
+Source Rect corners are (0, 0) and (src.width(), src.height()).
+Destination Rect corners are (dstX, dstY) and (dstX + Surface width(), dstY + Surface height()).
+Copies each readable pixel intersecting both rectangles, without scaling,
+converting to Surface colorType() and Surface alphaType() if required.
+
+#Param src storage for pixels to copy to Surface ##
+#Param dstX x position relative to Surface to begin copy; may be negative ##
+#Param dstY x position relative to Surface to begin copy; may be negative ##
+
+#Example
+ // todo
+##
+
+#SeeAlso readPixels peekPixels
#Method ##
diff --git a/include/core/SkSurface.h b/include/core/SkSurface.h
index d621fdf062..a4a62d0621 100644
--- a/include/core/SkSurface.h
+++ b/include/core/SkSurface.h
@@ -354,6 +354,19 @@ public:
int srcX, int srcY);
bool readPixels(const SkBitmap& dst, int srcX, int srcY);
+ /**
+ * Special version of drawing a pixmap to the surface (without going through the canvas).
+ * - the implied blendmode is kSrc (overwrite the surface pixel values)
+ * - any settings on the surface's canvas are ignored: matrix, clipping, etc.
+ */
+ void writePixels(const SkPixmap& src, int dstX, int dstY);
+
+ /**
+ * Helper that extracts the pixmap from the bitmap (if possible), and then calls writePixels
+ * with that pixmap.
+ */
+ void writePixels(const SkBitmap& src, int dstX, int dstY);
+
const SkSurfaceProps& props() const { return fProps; }
/**
diff --git a/src/image/SkSurface.cpp b/src/image/SkSurface.cpp
index ef6d809957..26ee40e9fb 100644
--- a/src/image/SkSurface.cpp
+++ b/src/image/SkSurface.cpp
@@ -184,6 +184,30 @@ bool SkSurface::readPixels(const SkBitmap& bitmap, int srcX, int srcY) {
return bitmap.peekPixels(&pm) && this->readPixels(pm, srcX, srcY);
}
+void SkSurface::writePixels(const SkPixmap& pmap, int x, int y) {
+ if (pmap.addr() == nullptr || pmap.width() <= 0 || pmap.height() <= 0) {
+ return;
+ }
+
+ const SkIRect srcR = SkIRect::MakeXYWH(x, y, pmap.width(), pmap.height());
+ const SkIRect dstR = SkIRect::MakeWH(this->width(), this->height());
+ if (SkIRect::Intersects(srcR, dstR)) {
+ ContentChangeMode mode = kRetain_ContentChangeMode;
+ if (srcR.contains(dstR)) {
+ mode = kDiscard_ContentChangeMode;
+ }
+ asSB(this)->aboutToDraw(mode);
+ asSB(this)->onWritePixels(pmap, x, y);
+ }
+}
+
+void SkSurface::writePixels(const SkBitmap& src, int x, int y) {
+ SkPixmap pm;
+ if (src.peekPixels(&pm)) {
+ this->writePixels(pm, x, y);
+ }
+}
+
GrBackendObject SkSurface::getTextureHandle(BackendHandleAccess access) {
return asSB(this)->onGetTextureHandle(access);
}
@@ -232,6 +256,7 @@ protected:
return MakeNull(info.width(), info.height());
}
sk_sp<SkImage> onNewImageSnapshot() override { return nullptr; }
+ void onWritePixels(const SkPixmap&, int x, int y) override {}
void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override {}
void onCopyOnWrite(ContentChangeMode) override {}
};
diff --git a/src/image/SkSurface_Base.h b/src/image/SkSurface_Base.h
index cce3dc0a88..56a09cf5e6 100644
--- a/src/image/SkSurface_Base.h
+++ b/src/image/SkSurface_Base.h
@@ -45,6 +45,8 @@ public:
*/
virtual sk_sp<SkImage> onNewImageSnapshot() = 0;
+ virtual void onWritePixels(const SkPixmap&, int x, int y) = 0;
+
/**
* Default implementation:
*
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index d7c1a46c58..04333ae508 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -125,6 +125,10 @@ sk_sp<SkImage> SkSurface_Gpu::onNewImageSnapshot() {
return image;
}
+void SkSurface_Gpu::onWritePixels(const SkPixmap& src, int x, int y) {
+ fDevice->writePixels(src, x, y);
+}
+
// Create a new render target and, if necessary, copy the contents of the old
// render target into it. Note that this flushes the SkGpuDevice but
// doesn't force an OpenGL flush.
diff --git a/src/image/SkSurface_Gpu.h b/src/image/SkSurface_Gpu.h
index 134eef23da..9699b01e05 100644
--- a/src/image/SkSurface_Gpu.h
+++ b/src/image/SkSurface_Gpu.h
@@ -27,6 +27,7 @@ public:
SkCanvas* onNewCanvas() override;
sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override;
sk_sp<SkImage> onNewImageSnapshot() override;
+ void onWritePixels(const SkPixmap&, int x, int y) override;
void onCopyOnWrite(ContentChangeMode) override;
void onDiscard() override;
GrSemaphoresSubmitted onFlush(int numSemaphores,
diff --git a/src/image/SkSurface_Raster.cpp b/src/image/SkSurface_Raster.cpp
index fab75ed817..c430ad90b0 100644
--- a/src/image/SkSurface_Raster.cpp
+++ b/src/image/SkSurface_Raster.cpp
@@ -22,6 +22,7 @@ public:
SkCanvas* onNewCanvas() override;
sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override;
sk_sp<SkImage> onNewImageSnapshot() override;
+ void onWritePixels(const SkPixmap&, int x, int y) override;
void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override;
void onCopyOnWrite(ContentChangeMode) override;
void onRestoreBackingMutability() override;
@@ -147,6 +148,10 @@ sk_sp<SkImage> SkSurface_Raster::onNewImageSnapshot() {
return SkMakeImageFromRasterBitmap(fBitmap, cpm);
}
+void SkSurface_Raster::onWritePixels(const SkPixmap& src, int x, int y) {
+ fBitmap.writePixels(src, x, y);
+}
+
void SkSurface_Raster::onRestoreBackingMutability() {
SkASSERT(!this->hasCachedImage()); // Shouldn't be any snapshots out there.
if (SkPixelRef* pr = fBitmap.pixelRef()) {
diff --git a/tests/PremulAlphaRoundTripTest.cpp b/tests/PremulAlphaRoundTripTest.cpp
index 2c3cb005b5..ba00363a62 100644
--- a/tests/PremulAlphaRoundTripTest.cpp
+++ b/tests/PremulAlphaRoundTripTest.cpp
@@ -44,7 +44,7 @@ const struct {
{ kBGRA_8888_SkColorType, pack_unpremul_bgra },
};
-static void fill_canvas(SkCanvas* canvas, SkColorType colorType, PackUnpremulProc proc) {
+static void fill_surface(SkSurface* surf, SkColorType colorType, PackUnpremulProc proc) {
// Don't strictly need a bitmap, but its a handy way to allocate the pixels
SkBitmap bmp;
bmp.allocN32Pixels(256, 256);
@@ -58,13 +58,12 @@ static void fill_canvas(SkCanvas* canvas, SkColorType colorType, PackUnpremulPro
const SkImageInfo info = SkImageInfo::Make(bmp.width(), bmp.height(),
colorType, kUnpremul_SkAlphaType);
- canvas->writePixels(info, bmp.getPixels(), bmp.rowBytes(), 0, 0);
+ surf->writePixels({info, bmp.getPixels(), bmp.rowBytes()}, 0, 0);
}
static void test_premul_alpha_roundtrip(skiatest::Reporter* reporter, SkSurface* surf) {
- SkCanvas* canvas = surf->getCanvas();
for (size_t upmaIdx = 0; upmaIdx < SK_ARRAY_COUNT(gUnpremul); ++upmaIdx) {
- fill_canvas(canvas, gUnpremul[upmaIdx].fColorType, gUnpremul[upmaIdx].fPackProc);
+ fill_surface(surf, gUnpremul[upmaIdx].fColorType, gUnpremul[upmaIdx].fPackProc);
const SkImageInfo info = SkImageInfo::Make(256, 256, gUnpremul[upmaIdx].fColorType,
kUnpremul_SkAlphaType);
@@ -77,7 +76,7 @@ static void test_premul_alpha_roundtrip(skiatest::Reporter* reporter, SkSurface*
readBmp2.eraseColor(0);
surf->readPixels(readBmp1, 0, 0);
- sk_tool_utils::write_pixels(canvas, readBmp1, 0, 0, gUnpremul[upmaIdx].fColorType,
+ sk_tool_utils::write_pixels(surf, readBmp1, 0, 0, gUnpremul[upmaIdx].fColorType,
kUnpremul_SkAlphaType);
surf->readPixels(readBmp2, 0, 0);
diff --git a/tests/WritePixelsTest.cpp b/tests/WritePixelsTest.cpp
index 2a2ee397ef..f2ad10c4f3 100644
--- a/tests/WritePixelsTest.cpp
+++ b/tests/WritePixelsTest.cpp
@@ -25,8 +25,6 @@
static const int DEV_W = 100, DEV_H = 100;
static const SkIRect DEV_RECT = SkIRect::MakeWH(DEV_W, DEV_H);
-static const SkRect DEV_RECT_S = SkRect::MakeWH(DEV_W * SK_Scalar1,
- DEV_H * SK_Scalar1);
static const U8CPU DEV_PAD = 0xee;
static SkPMColor get_canvas_color(int x, int y) {
@@ -113,23 +111,15 @@ static uint32_t get_bitmap_color(int x, int y, int w, SkColorType ct, SkAlphaTyp
return pack_color_type(ct, a, r, g , b);
}
-static void fill_canvas(SkCanvas* canvas) {
+static void fill_surface(SkSurface* surface) {
SkBitmap bmp;
- if (bmp.isNull()) {
- bmp.allocN32Pixels(DEV_W, DEV_H);
- for (int y = 0; y < DEV_H; ++y) {
- for (int x = 0; x < DEV_W; ++x) {
- *bmp.getAddr32(x, y) = get_canvas_color(x, y);
- }
+ bmp.allocN32Pixels(DEV_W, DEV_H);
+ for (int y = 0; y < DEV_H; ++y) {
+ for (int x = 0; x < DEV_W; ++x) {
+ *bmp.getAddr32(x, y) = get_canvas_color(x, y);
}
}
- canvas->save();
- canvas->setMatrix(SkMatrix::I());
- canvas->clipRect(DEV_RECT_S, kReplace_SkClipOp);
- SkPaint paint;
- paint.setBlendMode(SkBlendMode::kSrc);
- canvas->drawBitmap(bmp, 0, 0, &paint);
- canvas->restore();
+ surface->writePixels(bmp, 0, 0);
}
/**
@@ -288,17 +278,17 @@ static bool setup_bitmap(SkBitmap* bm, SkColorType ct, SkAlphaType at, int w, in
return true;
}
-static void call_writepixels(SkCanvas* canvas) {
+static void call_writepixels(SkSurface* surface) {
const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
SkPMColor pixel = 0;
- canvas->writePixels(info, &pixel, sizeof(SkPMColor), 0, 0);
+ surface->writePixels({info, &pixel, sizeof(SkPMColor)}, 0, 0);
}
DEF_TEST(WritePixelsSurfaceGenID, reporter) {
const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
auto surface(SkSurface::MakeRaster(info));
uint32_t genID1 = surface->generationID();
- call_writepixels(surface->getCanvas());
+ call_writepixels(surface.get());
uint32_t genID2 = surface->generationID();
REPORTER_ASSERT(reporter, genID1 != genID2);
}
@@ -369,14 +359,14 @@ static void test_write_pixels(skiatest::Reporter* reporter, SkSurface* surface)
const SkColorType ct = gSrcConfigs[c].fColorType;
const SkAlphaType at = gSrcConfigs[c].fAlphaType;
- fill_canvas(canvas);
+ fill_surface(surface);
SkBitmap bmp;
REPORTER_ASSERT(reporter, setup_bitmap(&bmp, ct, at, rect.width(),
rect.height(), SkToBool(tightBmp)));
uint32_t idBefore = surface->generationID();
// sk_tool_utils::write_pixels(&canvas, bmp, rect.fLeft, rect.fTop, ct, at);
- canvas->writePixels(bmp, rect.fLeft, rect.fTop);
+ surface->writePixels(bmp, rect.fLeft, rect.fTop);
uint32_t idAfter = surface->generationID();
REPORTER_ASSERT(reporter, check_write(reporter, surface, bmp,
@@ -469,7 +459,7 @@ static sk_sp<SkImage> upload(const sk_sp<SkSurface>& surf, SkColor color) {
bm.allocPixels(smII);
bm.eraseColor(color);
- surf->getCanvas()->writePixels(bm, 0, 0);
+ surf->writePixels(bm, 0, 0);
return surf->makeImageSnapshot();
}
diff --git a/tools/sk_tool_utils.cpp b/tools/sk_tool_utils.cpp
index 4c4474cc57..f0672070f1 100644
--- a/tools/sk_tool_utils.cpp
+++ b/tools/sk_tool_utils.cpp
@@ -144,6 +144,12 @@ void write_pixels(SkCanvas* canvas, const SkBitmap& bitmap, int x, int y,
canvas->writePixels(info, tmp.getPixels(), tmp.rowBytes(), x, y);
}
+void write_pixels(SkSurface* surface, const SkBitmap& src, int x, int y,
+ SkColorType colorType, SkAlphaType alphaType) {
+ const SkImageInfo info = SkImageInfo::Make(src.width(), src.height(), colorType, alphaType);
+ surface->writePixels({info, src.getPixels(), src.rowBytes()}, x, y);
+}
+
sk_sp<SkShader> create_checkerboard_shader(SkColor c1, SkColor c2, int size) {
SkBitmap bm;
bm.allocPixels(SkImageInfo::MakeS32(2 * size, 2 * size, kPremul_SkAlphaType));
diff --git a/tools/sk_tool_utils.h b/tools/sk_tool_utils.h
index a1b5b7fe37..6c1adf8e26 100644
--- a/tools/sk_tool_utils.h
+++ b/tools/sk_tool_utils.h
@@ -70,10 +70,11 @@ namespace sk_tool_utils {
void release_portable_typefaces();
/**
- * Call canvas->writePixels() by using the pixels from bitmap, but with an info that claims
+ * Call writePixels() by using the pixels from bitmap, but with an info that claims
* the pixels are colorType + alphaType
*/
void write_pixels(SkCanvas*, const SkBitmap&, int x, int y, SkColorType, SkAlphaType);
+ void write_pixels(SkSurface*, const SkBitmap&, int x, int y, SkColorType, SkAlphaType);
/**
* Returns true iff all of the pixels between the two images differ by <= the maxDiff value