aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gm/colormatrix.cpp120
-rw-r--r--include/core/SkImage.h6
-rw-r--r--src/core/SkRecorder.cpp24
-rw-r--r--src/image/SkImage.cpp38
-rw-r--r--src/image/SkImagePriv.h7
-rw-r--r--src/image/SkImage_Gpu.cpp51
-rw-r--r--src/image/SkImage_Raster.cpp17
-rw-r--r--src/image/SkSurface_Raster.cpp2
-rw-r--r--tests/DeferredCanvasTest.cpp2
-rw-r--r--tests/SkImageTest.cpp2
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;