diff options
author | Mike Reed <reed@google.com> | 2018-02-08 14:10:40 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-02-08 19:34:50 +0000 |
commit | 4c790bd7dd8a6edacfc39b65b7043742331ab4da (patch) | |
tree | 1d66da0bfa6b7627315388b0d3f712897ea03bbd | |
parent | b9fc24e465767db8bd9dbddfd67c905392346e66 (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.bmh | 54 | ||||
-rw-r--r-- | include/core/SkSurface.h | 13 | ||||
-rw-r--r-- | src/image/SkSurface.cpp | 25 | ||||
-rw-r--r-- | src/image/SkSurface_Base.h | 2 | ||||
-rw-r--r-- | src/image/SkSurface_Gpu.cpp | 4 | ||||
-rw-r--r-- | src/image/SkSurface_Gpu.h | 1 | ||||
-rw-r--r-- | src/image/SkSurface_Raster.cpp | 5 | ||||
-rw-r--r-- | tests/PremulAlphaRoundTripTest.cpp | 9 | ||||
-rw-r--r-- | tests/WritePixelsTest.cpp | 34 | ||||
-rw-r--r-- | tools/sk_tool_utils.cpp | 6 | ||||
-rw-r--r-- | tools/sk_tool_utils.h | 3 |
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 |