diff options
-rw-r--r-- | gm/colormatrix.cpp | 120 | ||||
-rw-r--r-- | include/core/SkImage.h | 6 | ||||
-rw-r--r-- | src/core/SkRecorder.cpp | 24 | ||||
-rw-r--r-- | src/image/SkImage.cpp | 38 | ||||
-rw-r--r-- | src/image/SkImagePriv.h | 7 | ||||
-rw-r--r-- | src/image/SkImage_Gpu.cpp | 51 | ||||
-rw-r--r-- | src/image/SkImage_Raster.cpp | 17 | ||||
-rw-r--r-- | src/image/SkSurface_Raster.cpp | 2 | ||||
-rw-r--r-- | tests/DeferredCanvasTest.cpp | 2 | ||||
-rw-r--r-- | tests/SkImageTest.cpp | 2 |
10 files changed, 162 insertions, 107 deletions
diff --git a/gm/colormatrix.cpp b/gm/colormatrix.cpp index 8dcdf15e50..a80f8cb581 100644 --- a/gm/colormatrix.cpp +++ b/gm/colormatrix.cpp @@ -8,60 +8,40 @@ #include "gm.h" #include "SkColorMatrixFilter.h" #include "SkGradientShader.h" +#include "SkImage.h" #define WIDTH 500 #define HEIGHT 500 -class SkDoOnce { -public: - SkDoOnce() : fOnce(false) {}; - - bool once() const { - if (fOnce) { - return false; - } - fOnce = true; - return true; - } - -private: - mutable bool fOnce; -}; - -static void setColorMatrix(SkPaint* paint, const SkColorMatrix& matrix) { +static void set_color_matrix(SkPaint* paint, const SkColorMatrix& matrix) { paint->setColorFilter(SkColorMatrixFilter::Create(matrix))->unref(); } -static void setArray(SkPaint* paint, const SkScalar array[]) { +static void set_array(SkPaint* paint, const SkScalar array[]) { paint->setColorFilter(SkColorMatrixFilter::Create(array))->unref(); } -namespace skiagm { - -class ColorMatrixGM : public GM { - SkDoOnce fOnce; - void init() { - if (fOnce.once()) { - fSolidBitmap = this->createSolidBitmap(64, 64); - fTransparentBitmap = this->createTransparentBitmap(64, 64); - } - } - +class ColorMatrixGM : public skiagm::GM { public: ColorMatrixGM() { this->setBGColor(sk_tool_utils::color_to_565(0xFF808080)); } protected: - virtual SkString onShortName() { + SkString onShortName() override { return SkString("colormatrix"); } - virtual SkISize onISize() { + SkISize onISize() override { return SkISize::Make(WIDTH, HEIGHT); } + + void onOnceBeforeDraw() override { + fSolidImg.reset(CreateSolidBitmap(64, 64)); + fTransparentImg.reset(CreateTransparentBitmap(64, 64)); + } - SkBitmap createSolidBitmap(int width, int height) { + static SkImage* CreateSolidBitmap(int width, int height) { SkBitmap bm; bm.allocN32Pixels(width, height); SkCanvas canvas(bm); @@ -74,11 +54,11 @@ protected: SkIntToScalar(y), SK_Scalar1, SK_Scalar1), paint); } } - return bm; + return SkImage::NewFromBitmap(bm); } // creates a bitmap with shades of transparent gray. - SkBitmap createTransparentBitmap(int width, int height) { + static SkImage* CreateTransparentBitmap(int width, int height) { SkBitmap bm; bm.allocN32Pixels(width, height); SkCanvas canvas(bm); @@ -90,58 +70,56 @@ protected: paint.setShader(SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kClamp_TileMode))->unref(); canvas.drawRect(SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)), paint); - return bm; + return SkImage::NewFromBitmap(bm); } - virtual void onDraw(SkCanvas* canvas) { - this->init(); - + void onDraw(SkCanvas* canvas) override { SkPaint paint; SkColorMatrix matrix; paint.setXfermodeMode(SkXfermode::kSrc_Mode); - const SkBitmap bmps[] = { fSolidBitmap, fTransparentBitmap }; + const SkImage* bmps[] = { fSolidImg, fTransparentImg }; for (size_t i = 0; i < SK_ARRAY_COUNT(bmps); ++i) { matrix.setIdentity(); - setColorMatrix(&paint, matrix); - canvas->drawBitmap(bmps[i], 0, 0, &paint); + set_color_matrix(&paint, matrix); + canvas->drawImage(bmps[i], 0, 0, &paint); matrix.setRotate(SkColorMatrix::kR_Axis, 90); - setColorMatrix(&paint, matrix); - canvas->drawBitmap(bmps[i], 80, 0, &paint); + set_color_matrix(&paint, matrix); + canvas->drawImage(bmps[i], 80, 0, &paint); matrix.setRotate(SkColorMatrix::kG_Axis, 90); - setColorMatrix(&paint, matrix); - canvas->drawBitmap(bmps[i], 160, 0, &paint); + set_color_matrix(&paint, matrix); + canvas->drawImage(bmps[i], 160, 0, &paint); matrix.setRotate(SkColorMatrix::kB_Axis, 90); - setColorMatrix(&paint, matrix); - canvas->drawBitmap(bmps[i], 240, 0, &paint); - + set_color_matrix(&paint, matrix); + canvas->drawImage(bmps[i], 240, 0, &paint); + /////////////////////////////////////////////// matrix.setSaturation(0.0f); - setColorMatrix(&paint, matrix); - canvas->drawBitmap(bmps[i], 0, 80, &paint); + set_color_matrix(&paint, matrix); + canvas->drawImage(bmps[i], 0, 80, &paint); matrix.setSaturation(0.5f); - setColorMatrix(&paint, matrix); - canvas->drawBitmap(bmps[i], 80, 80, &paint); + set_color_matrix(&paint, matrix); + canvas->drawImage(bmps[i], 80, 80, &paint); matrix.setSaturation(1.0f); - setColorMatrix(&paint, matrix); - canvas->drawBitmap(bmps[i], 160, 80, &paint); + set_color_matrix(&paint, matrix); + canvas->drawImage(bmps[i], 160, 80, &paint); matrix.setSaturation(2.0f); - setColorMatrix(&paint, matrix); - canvas->drawBitmap(bmps[i], 240, 80, &paint); - + set_color_matrix(&paint, matrix); + canvas->drawImage(bmps[i], 240, 80, &paint); + /////////////////////////////////////////////// matrix.setRGB2YUV(); - setColorMatrix(&paint, matrix); - canvas->drawBitmap(bmps[i], 0, 160, &paint); + set_color_matrix(&paint, matrix); + canvas->drawImage(bmps[i], 0, 160, &paint); matrix.setYUV2RGB(); - setColorMatrix(&paint, matrix); - canvas->drawBitmap(bmps[i], 80, 160, &paint); + set_color_matrix(&paint, matrix); + canvas->drawImage(bmps[i], 80, 160, &paint); SkScalar s1 = SK_Scalar1; SkScalar s255 = SkIntToScalar(255); @@ -153,22 +131,18 @@ protected: s1, 0, 0, 0, 0, }; - setArray(&paint, data); - canvas->drawBitmap(bmps[i], 160, 160, &paint); - + set_array(&paint, data); + canvas->drawImage(bmps[i], 160, 160, &paint); + /////////////////////////////////////////////// canvas->translate(0, 240); } } private: - SkBitmap fSolidBitmap; - SkBitmap fTransparentBitmap; - typedef GM INHERITED; -}; - -////////////////////////////////////////////////////////////////////////////// + SkAutoTUnref<SkImage> fSolidImg; + SkAutoTUnref<SkImage> fTransparentImg; -static GM* MyFactory(void*) { return new ColorMatrixGM; } -static GMRegistry reg(MyFactory); + typedef skiagm::GM INHERITED; +}; +DEF_GM( return new ColorMatrixGM; ) -} diff --git a/include/core/SkImage.h b/include/core/SkImage.h index 7557e8e41d..41a1bd8527 100644 --- a/include/core/SkImage.h +++ b/include/core/SkImage.h @@ -62,6 +62,12 @@ public: RasterReleaseProc, ReleaseContext); /** + * Construct a new image from the specified bitmap. If the bitmap is marked immutable, and + * its pixel memory is shareable, it may be shared instead of copied. + */ + static SkImage* NewFromBitmap(const SkBitmap&); + + /** * Construct a new SkImage based on the given ImageGenerator. * This function will always take ownership of the passed * ImageGenerator. Returns NULL on error. diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp index 775a7e0c55..7433a5b5bf 100644 --- a/src/core/SkRecorder.cpp +++ b/src/core/SkRecorder.cpp @@ -12,6 +12,8 @@ #include "SkPictureUtils.h" #include "SkRecorder.h" +//#define WRAP_BITMAP_AS_IMAGE + SkDrawableList::~SkDrawableList() { fArray.unrefAll(); } @@ -170,7 +172,14 @@ void SkRecorder::onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, const SkPaint* paint) { +#ifdef WRAP_BITMAP_AS_IMAGE + SkAutoTUnref<SkImage> image(SkImage::NewFromBitmap(bitmap)); + if (image) { + this->onDrawImage(image, left, top, paint); + } +#else APPEND(DrawBitmap, this->copy(paint), bitmap, left, top); +#endif } void SkRecorder::onDrawBitmapRect(const SkBitmap& bitmap, @@ -178,6 +187,13 @@ void SkRecorder::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint, DrawBitmapRectFlags flags) { +#ifdef WRAP_BITMAP_AS_IMAGE + // TODO: need a way to support the flags for images... + SkAutoTUnref<SkImage> image(SkImage::NewFromBitmap(bitmap)); + if (image) { + this->onDrawImageRect(image, src, dst, paint); + } +#else TRY_MINIRECORDER(drawBitmapRectToRect, bitmap, src, dst, paint, flags); if (kBleed_DrawBitmapRectFlag == flags) { APPEND(DrawBitmapRectToRectBleed, @@ -187,13 +203,21 @@ void SkRecorder::onDrawBitmapRect(const SkBitmap& bitmap, SkASSERT(kNone_DrawBitmapRectFlag == flags); APPEND(DrawBitmapRectToRect, this->copy(paint), bitmap, this->copy(src), dst); +#endif } void SkRecorder::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, const SkPaint* paint) { +#ifdef WRAP_BITMAP_AS_IMAGE + SkAutoTUnref<SkImage> image(SkImage::NewFromBitmap(bitmap)); + if (image) { + this->onDrawImageNine(image, center, dst, paint); + } +#else APPEND(DrawBitmapNine, this->copy(paint), bitmap, center, dst); +#endif } void SkRecorder::onDrawImage(const SkImage* image, SkScalar left, SkScalar top, diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp index 1d61438707..d3533a9a4a 100644 --- a/src/image/SkImage.cpp +++ b/src/image/SkImage.cpp @@ -11,12 +11,15 @@ #include "SkImageGenerator.h" #include "SkImagePriv.h" #include "SkImage_Base.h" +#include "SkPixelRef.h" #include "SkReadPixelsRec.h" #include "SkString.h" #include "SkSurface.h" + #if SK_SUPPORT_GPU #include "GrTexture.h" #include "GrContext.h" +#include "SkImage_Gpu.h" #endif uint32_t SkImage::NextUniqueID() { @@ -227,6 +230,41 @@ bool SkImage::readPixels(const SkPixmap& pmap, int srcX, int srcY) const { /////////////////////////////////////////////////////////////////////////////////////////////////// +SkImage* SkImage::NewFromBitmap(const SkBitmap& bm) { + SkPixelRef* pr = bm.pixelRef(); + if (NULL == pr) { + return NULL; + } + +#if SK_SUPPORT_GPU + if (GrTexture* tex = pr->getTexture()) { + SkAutoTUnref<GrTexture> unrefCopy; + if (!bm.isImmutable()) { + const bool notBudgeted = false; + tex = GrDeepCopyTexture(tex, notBudgeted); + if (NULL == tex) { + return NULL; + } + unrefCopy.reset(tex); + } + const SkImageInfo info = bm.info(); + return SkNEW_ARGS(SkImage_Gpu, (info.width(), info.height(), info.alphaType(), + tex, 0, SkSurface::kNo_Budgeted)); + } +#endif + + // Encoded version? + if (SkData* encoded = pr->refEncodedData()) { + SkAutoTUnref<SkData> data(encoded); + return SkImage::NewFromEncoded(encoded); // todo: add origin/subset/etc? + } + + // This will check for immutable (share or copy) + return SkNewImageFromRasterBitmap(bm, false, NULL); +} + +////////////////////////////////////////////////////////////////////////////////////// + #if !SK_SUPPORT_GPU SkImage* SkImage::NewFromTexture(GrContext*, const GrBackendTextureDesc&, SkAlphaType, diff --git a/src/image/SkImagePriv.h b/src/image/SkImagePriv.h index d3b1c79a79..afaf3f1736 100644 --- a/src/image/SkImagePriv.h +++ b/src/image/SkImagePriv.h @@ -23,11 +23,14 @@ extern SkImage* SkNewImageFromPixelRef(const SkImageInfo&, SkPixelRef*, * be shared if either the bitmap is marked as immutable, or canSharePixelRef * is true. * + * It is illegal to call this with a texture-backed bitmap. + * * If the bitmap's colortype cannot be converted into a corresponding * SkImageInfo, or the bitmap's pixels cannot be accessed, this will return * NULL. */ -extern SkImage* SkNewImageFromBitmap(const SkBitmap&, bool canSharePixelRef, const SkSurfaceProps*); +extern SkImage* SkNewImageFromRasterBitmap(const SkBitmap&, bool forceSharePixelRef, + const SkSurfaceProps*); static inline size_t SkImageMinRowBytes(const SkImageInfo& info) { size_t minRB = info.minRowBytes(); @@ -53,4 +56,6 @@ extern void SkTextureImageApplyBudgetedDecision(SkImage* textureImage); // surface needs to perform a copy-on-write extern void SkTextureImageSetTexture(SkImage* image, GrTexture* texture); +GrTexture* GrDeepCopyTexture(GrTexture* src, bool isBudgeted); + #endif diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp index 4003631c8a..d9ae619e5f 100644 --- a/src/image/SkImage_Gpu.cpp +++ b/src/image/SkImage_Gpu.cpp @@ -144,42 +144,27 @@ SkImage* SkImage::NewFromAdoptedTexture(GrContext* ctx, const GrBackendTextureDe return new_wrapped_texture_common(ctx, desc, at, kAdopt_GrWrapOwnership, NULL, NULL); } -SkImage* SkImage::NewFromTextureCopy(GrContext* ctx, const GrBackendTextureDesc& srcDesc, +SkImage* SkImage::NewFromTextureCopy(GrContext* ctx, const GrBackendTextureDesc& desc, SkAlphaType at) { - const bool isBudgeted = true; - const SkSurface::Budgeted budgeted = SkSurface::kYes_Budgeted; - - if (srcDesc.fWidth <= 0 || srcDesc.fHeight <= 0) { + if (desc.fWidth <= 0 || desc.fHeight <= 0) { return NULL; } + SkAutoTUnref<GrTexture> src(ctx->textureProvider()->wrapBackendTexture( - srcDesc, kBorrow_GrWrapOwnership)); + desc, kBorrow_GrWrapOwnership)); if (!src) { return NULL; } - GrSurfaceDesc dstDesc; - // need to be a rendertarget for readpixels to work, instead of kNone_GrSurfaceFlags - dstDesc.fFlags = kRenderTarget_GrSurfaceFlag; - dstDesc.fOrigin = srcDesc.fOrigin; - dstDesc.fWidth = srcDesc.fWidth; - dstDesc.fHeight = srcDesc.fHeight; - dstDesc.fConfig = srcDesc.fConfig; - dstDesc.fSampleCnt = srcDesc.fSampleCnt; - - SkAutoTUnref<GrTexture> dst(ctx->textureProvider()->createTexture( - dstDesc, isBudgeted, NULL, 0)); + const bool isBudgeted = true; + SkAutoTUnref<GrTexture> dst(GrDeepCopyTexture(src, isBudgeted)); if (!dst) { return NULL; } - const SkIRect srcR = SkIRect::MakeWH(dstDesc.fWidth, dstDesc.fHeight); - const SkIPoint dstP = SkIPoint::Make(0, 0); - ctx->copySurface(dst, src, srcR, dstP, GrContext::kFlushWrites_PixelOp); - + const SkSurface::Budgeted budgeted = SkSurface::kYes_Budgeted; const int sampleCount = 0; // todo: make this an explicit parameter to newSurface()? - return SkNEW_ARGS(SkImage_Gpu, (dstDesc.fWidth, dstDesc.fHeight, at, dst, sampleCount, - budgeted)); + return SkNEW_ARGS(SkImage_Gpu, (desc.fWidth, desc.fHeight, at, dst, sampleCount, budgeted)); } SkImage* SkImage::NewFromYUVTexturesCopy(GrContext* ctx , SkYUVColorSpace colorSpace, @@ -256,3 +241,23 @@ SkImage* SkImage::NewFromYUVTexturesCopy(GrContext* ctx , SkYUVColorSpace colorS return SkNEW_ARGS(SkImage_Gpu, (dstDesc.fWidth, dstDesc.fHeight, kOpaque_SkAlphaType, dst, 0, budgeted)); } + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +GrTexture* GrDeepCopyTexture(GrTexture* src, bool budgeted) { + GrContext* ctx = src->getContext(); + + GrSurfaceDesc desc = src->desc(); + // need to be a rendertarget for readpixels to work, instead of kNone_GrSurfaceFlags + desc.fFlags = kRenderTarget_GrSurfaceFlag; + GrTexture* dst = ctx->textureProvider()->createTexture(desc, budgeted, NULL, 0); + if (!dst) { + return NULL; + } + + const SkIRect srcR = SkIRect::MakeWH(desc.fWidth, desc.fHeight); + const SkIPoint dstP = SkIPoint::Make(0, 0); + ctx->copySurface(dst, src, srcR, dstP, GrContext::kFlushWrites_PixelOp); + return dst; +} + diff --git a/src/image/SkImage_Raster.cpp b/src/image/SkImage_Raster.cpp index 0316d53708..250e3624ea 100644 --- a/src/image/SkImage_Raster.cpp +++ b/src/image/SkImage_Raster.cpp @@ -227,21 +227,24 @@ SkImage* SkNewImageFromPixelRef(const SkImageInfo& info, SkPixelRef* pr, return SkNEW_ARGS(SkImage_Raster, (info, pr, pixelRefOrigin, rowBytes, props)); } -SkImage* SkNewImageFromBitmap(const SkBitmap& bm, bool canSharePixelRef, - const SkSurfaceProps* props) { +SkImage* SkNewImageFromRasterBitmap(const SkBitmap& bm, bool forceSharePixelRef, + const SkSurfaceProps* props) { + SkASSERT(NULL == bm.getTexture()); + if (!SkImage_Raster::ValidArgs(bm.info(), bm.rowBytes(), NULL, NULL)) { return NULL; } SkImage* image = NULL; - if (canSharePixelRef || bm.isImmutable()) { + if (forceSharePixelRef || bm.isImmutable()) { image = SkNEW_ARGS(SkImage_Raster, (bm, props)); } else { - bm.lockPixels(); - if (bm.getPixels()) { - image = SkImage::NewRasterCopy(bm.info(), bm.getPixels(), bm.rowBytes()); + SkBitmap tmp(bm); + tmp.lockPixels(); + if (tmp.getPixels()) { + image = SkImage::NewRasterCopy(tmp.info(), tmp.getPixels(), tmp.rowBytes(), + tmp.getColorTable()); } - bm.unlockPixels(); // we don't expose props to NewRasterCopy (need a private vers) so post-init it here if (image && props) { diff --git a/src/image/SkSurface_Raster.cpp b/src/image/SkSurface_Raster.cpp index 4e0ba088b1..d66aed213a 100644 --- a/src/image/SkSurface_Raster.cpp +++ b/src/image/SkSurface_Raster.cpp @@ -118,7 +118,7 @@ void SkSurface_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, } SkImage* SkSurface_Raster::onNewImageSnapshot(Budgeted) { - return SkNewImageFromBitmap(fBitmap, fWeOwnThePixels, &this->props()); + return SkNewImageFromRasterBitmap(fBitmap, fWeOwnThePixels, &this->props()); } void SkSurface_Raster::onCopyOnWrite(ContentChangeMode mode) { diff --git a/tests/DeferredCanvasTest.cpp b/tests/DeferredCanvasTest.cpp index fff213b607..a34f5bcedc 100644 --- a/tests/DeferredCanvasTest.cpp +++ b/tests/DeferredCanvasTest.cpp @@ -64,7 +64,7 @@ public: } SkImage* onNewImageSnapshot(Budgeted) override { - return SkNewImageFromBitmap(fBitmap, true, &this->props()); + return SkNewImageFromRasterBitmap(fBitmap, true, &this->props()); } void onCopyOnWrite(ContentChangeMode mode) override { diff --git a/tests/SkImageTest.cpp b/tests/SkImageTest.cpp index c058ef062b..2f23b3f661 100644 --- a/tests/SkImageTest.cpp +++ b/tests/SkImageTest.cpp @@ -26,7 +26,7 @@ DEF_TEST(SkImageFromBitmap_extractSubset, reporter) { canvas.drawIRect(r, p); SkBitmap dstBitmap; srcBitmap.extractSubset(&dstBitmap, r); - image.reset(SkNewImageFromBitmap(dstBitmap, true, NULL)); + image.reset(SkNewImageFromRasterBitmap(dstBitmap, true, NULL)); } SkBitmap tgt; |