aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkDevice.h4
-rw-r--r--include/core/SkImage.h13
-rw-r--r--include/utils/SkDeferredCanvas.h3
-rw-r--r--src/core/SkCanvas.cpp56
-rw-r--r--src/core/SkDevice.cpp19
-rw-r--r--src/core/SkPaintPriv.cpp6
-rw-r--r--src/core/SkPaintPriv.h10
-rw-r--r--src/core/SkPictureRecord.cpp17
-rw-r--r--src/core/SkPictureRecord.h3
-rw-r--r--src/gpu/SkGpuDevice.cpp42
-rw-r--r--src/gpu/SkGpuDevice.h3
-rw-r--r--src/image/SkImage.cpp9
-rw-r--r--src/image/SkImage_Base.h3
-rw-r--r--src/image/SkImage_Gpu.cpp9
-rw-r--r--src/image/SkImage_Gpu.h3
-rw-r--r--src/image/SkImage_Raster.cpp13
-rw-r--r--src/pipe/SkGPipePriv.h20
-rw-r--r--src/pipe/SkGPipeRead.cpp47
-rw-r--r--src/pipe/SkGPipeWrite.cpp94
-rw-r--r--src/utils/SkDeferredCanvas.cpp71
20 files changed, 367 insertions, 78 deletions
diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h
index 8a219d7053..b474687cfb 100644
--- a/include/core/SkDevice.h
+++ b/include/core/SkDevice.h
@@ -209,6 +209,10 @@ protected:
const SkPaint& paint,
SkCanvas::DrawBitmapRectFlags flags) = 0;
+ virtual void drawImage(const SkDraw&, const SkImage*, SkScalar x, SkScalar y, const SkPaint&);
+ virtual void drawImageRect(const SkDraw&, const SkImage*, const SkRect* src, const SkRect& dst,
+ const SkPaint&);
+
/**
* Does not handle text decoration.
* Decorations (underline and stike-thru) will be handled by SkCanvas.
diff --git a/include/core/SkImage.h b/include/core/SkImage.h
index ec85516619..ebc9a29394 100644
--- a/include/core/SkImage.h
+++ b/include/core/SkImage.h
@@ -172,19 +172,6 @@ private:
static uint32_t NextUniqueID();
typedef SkRefCnt INHERITED;
-
- friend class SkCanvas;
-
- void draw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const;
-
- /**
- * Draw the image, cropped to the src rect, to the dst rect of a canvas.
- * If src is larger than the bounds of the image, the rest of the image is
- * filled with transparent black pixels.
- *
- * See SkCanvas::drawBitmapRectToRect for similar behavior.
- */
- void drawRect(SkCanvas*, const SkRect* src, const SkRect& dst, const SkPaint*) const;
};
#endif
diff --git a/include/utils/SkDeferredCanvas.h b/include/utils/SkDeferredCanvas.h
index ac8556f539..a8330493a7 100644
--- a/include/utils/SkDeferredCanvas.h
+++ b/include/utils/SkDeferredCanvas.h
@@ -177,12 +177,9 @@ protected:
void onDrawBitmap(const SkBitmap&, SkScalar left, SkScalar top, const SkPaint*) override;
void onDrawBitmapRect(const SkBitmap&, const SkRect* src, const SkRect& dst, const SkPaint*,
DrawBitmapRectFlags flags) override;
-#if 0
- // rely on conversion to bitmap(for now)
void onDrawImage(const SkImage*, SkScalar left, SkScalar top, const SkPaint*) override;
void onDrawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,
const SkPaint*) override;
-#endif
void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
const SkPaint*) override;
void onDrawSprite(const SkBitmap&, int left, int top, const SkPaint*) override;
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 3e3f714880..34d6aaa0ab 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -1734,12 +1734,15 @@ void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
this->onDrawPath(path, paint);
}
-void SkCanvas::drawImage(const SkImage* image, SkScalar dx, SkScalar dy, const SkPaint* paint) {
- this->onDrawImage(image, dx, dy, paint);
+void SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
+ this->onDrawImage(image, x, y, paint);
}
void SkCanvas::drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
const SkPaint* paint) {
+ if (dst.isEmpty()) {
+ return;
+ }
this->onDrawImageRect(image, src, dst, paint);
}
@@ -1959,15 +1962,58 @@ void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
LOOPER_END
}
-void SkCanvas::onDrawImage(const SkImage* image, SkScalar dx, SkScalar dy, const SkPaint* paint) {
+void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()");
- image->draw(this, dx, dy, paint);
+ SkRect bounds = SkRect::MakeXYWH(x, y,
+ SkIntToScalar(image->width()), SkIntToScalar(image->height()));
+ if (NULL == paint || paint->canComputeFastBounds()) {
+ if (paint) {
+ paint->computeFastBounds(bounds, &bounds);
+ }
+ if (this->quickReject(bounds)) {
+ return;
+ }
+ }
+
+ SkLazyPaint lazy;
+ if (NULL == paint) {
+ paint = lazy.init();
+ }
+
+ LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &bounds)
+
+ while (iter.next()) {
+ iter.fDevice->drawImage(iter, image, x, y, looper.paint());
+ }
+
+ LOOPER_END
}
void SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
const SkPaint* paint) {
TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()");
- image->drawRect(this, src, dst, paint);
+ SkRect storage;
+ const SkRect* bounds = &dst;
+ if (NULL == paint || paint->canComputeFastBounds()) {
+ if (paint) {
+ bounds = &paint->computeFastBounds(dst, &storage);
+ }
+ if (this->quickReject(*bounds)) {
+ return;
+ }
+ }
+ SkLazyPaint lazy;
+ if (NULL == paint) {
+ paint = lazy.init();
+ }
+
+ LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
+
+ while (iter.next()) {
+ iter.fDevice->drawImageRect(iter, image, src, dst, looper.paint());
+ }
+
+ LOOPER_END
}
void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) {
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 6be9178f23..37fafd8dfb 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -9,6 +9,7 @@
#include "SkDeviceProperties.h"
#include "SkDraw.h"
#include "SkDrawFilter.h"
+#include "SkImage_Base.h"
#include "SkMetaData.h"
#include "SkPatchUtils.h"
#include "SkPathMeasure.h"
@@ -165,6 +166,24 @@ void SkBaseDevice::drawTextBlob(const SkDraw& draw, const SkTextBlob* blob, SkSc
}
}
+void SkBaseDevice::drawImage(const SkDraw& draw, const SkImage* image, SkScalar x, SkScalar y,
+ const SkPaint& paint) {
+ // Default impl : turns everything into raster bitmap
+ SkBitmap bm;
+ if (as_IB(image)->getROPixels(&bm)) {
+ this->drawBitmap(draw, bm, SkMatrix::MakeTrans(x, y), paint);
+ }
+}
+
+void SkBaseDevice::drawImageRect(const SkDraw& draw, const SkImage* image, const SkRect* src,
+ const SkRect& dst, const SkPaint& paint) {
+ // Default impl : turns everything into raster bitmap
+ SkBitmap bm;
+ if (as_IB(image)->getROPixels(&bm)) {
+ this->drawBitmapRect(draw, bm, src, dst, paint, SkCanvas::kNone_DrawBitmapRectFlag);
+ }
+}
+
bool SkBaseDevice::readPixels(const SkImageInfo& info, void* dstP, size_t rowBytes, int x, int y) {
#ifdef SK_DEBUG
SkASSERT(info.width() > 0 && info.height() > 0);
diff --git a/src/core/SkPaintPriv.cpp b/src/core/SkPaintPriv.cpp
index c6957cd1ca..3ced573929 100644
--- a/src/core/SkPaintPriv.cpp
+++ b/src/core/SkPaintPriv.cpp
@@ -9,6 +9,7 @@
#include "SkBitmap.h"
#include "SkColorFilter.h"
+#include "SkImage.h"
#include "SkPaint.h"
#include "SkShader.h"
@@ -49,3 +50,8 @@ bool isPaintOpaque(const SkPaint* paint, const SkBitmap* bmpReplacesShader) {
return isPaintOpaque(paint, contentType);
}
+
+bool isPaintOpaque(const SkPaint* paint, const SkImage* image) {
+ return isPaintOpaque(paint, image->isOpaque() ?
+ kOpaque_SkPaintBitmapOpacity : kUnknown_SkPaintBitmapOpacity);
+}
diff --git a/src/core/SkPaintPriv.h b/src/core/SkPaintPriv.h
index 88fc4fc349..be441b8f72 100644
--- a/src/core/SkPaintPriv.h
+++ b/src/core/SkPaintPriv.h
@@ -8,11 +8,12 @@
#ifndef SkPaintPriv_DEFINED
#define SkPaintPriv_DEFINED
+#include "SkTypes.h"
+
class SkBitmap;
+class SkImage;
class SkPaint;
-#include "SkTypes.h"
-
enum SkPaintBitmapOpacity {
// No content replaces the paint's color
kNoBitmap_SkPaintBitmapOpacity = 0,
@@ -40,6 +41,7 @@ bool isPaintOpaque(const SkPaint* paint, SkPaintBitmapOpacity contentType);
shader.
@return true if paint is opaque
*/
-bool isPaintOpaque(const SkPaint* paint,
- const SkBitmap* bmpReplacesShader = NULL);
+bool isPaintOpaque(const SkPaint* paint, const SkBitmap* bmpReplacesShader = NULL);
+bool isPaintOpaque(const SkPaint* paint, const SkImage* image);
+
#endif
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index 53ecdd0be6..07811fb128 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -7,6 +7,7 @@
#include "SkPictureRecord.h"
#include "SkDevice.h"
+#include "SkImage_Base.h"
#include "SkPatchUtils.h"
#include "SkPixelRef.h"
#include "SkRRect.h"
@@ -563,6 +564,22 @@ void SkPictureRecord::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src
this->validate(initialOffset, size);
}
+void SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
+ const SkPaint* paint) {
+ SkBitmap bm;
+ if (as_IB(image)->getROPixels(&bm)) {
+ this->SkPictureRecord::onDrawBitmap(bm, x, y, paint);
+ }
+}
+
+void SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
+ const SkPaint* paint) {
+ SkBitmap bm;
+ if (as_IB(image)->getROPixels(&bm)) {
+ this->SkPictureRecord::onDrawBitmapRect(bm, src, dst, paint, kNone_DrawBitmapRectFlag);
+ }
+}
+
void SkPictureRecord::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
const SkRect& dst, const SkPaint* paint) {
// op + paint index + bitmap id + center + dst rect
diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h
index 5e2d5a10e4..7a6fc813a5 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -184,12 +184,9 @@ protected:
void onDrawBitmap(const SkBitmap&, SkScalar left, SkScalar top, const SkPaint*) override;
void onDrawBitmapRect(const SkBitmap&, const SkRect* src, const SkRect& dst, const SkPaint*,
DrawBitmapRectFlags flags) override;
-#if 0
- // rely on conversion to bitmap (for now)
void onDrawImage(const SkImage*, SkScalar left, SkScalar top, const SkPaint*) override;
void onDrawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,
const SkPaint*) override;
-#endif
void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
const SkPaint*) override;
void onDrawSprite(const SkBitmap&, int left, int top, const SkPaint*) override;
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 6ff0538ee2..9518600e99 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -21,6 +21,7 @@
#include "SkErrorInternals.h"
#include "SkGlyphCache.h"
#include "SkGrTexturePixelRef.h"
+#include "SkImage_Base.h"
#include "SkImageFilter.h"
#include "SkLayerInfo.h"
#include "SkMaskFilter.h"
@@ -1730,6 +1731,47 @@ bool SkGpuDevice::filterImage(const SkImageFilter* filter, const SkBitmap& src,
filter, ctx, result, offset);
}
+static SkImageInfo make_info(GrTexture* tex, int w, int h, bool isOpaque) {
+ const GrPixelConfig config = tex->config();
+ SkColorType ct;
+ SkAlphaType at = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
+ if (!GrPixelConfig2ColorAndProfileType(config, &ct, NULL)) {
+ ct = kUnknown_SkColorType;
+ }
+ return SkImageInfo::Make(w, h, ct, at);
+}
+
+static bool wrap_as_bm(const SkImage* image, SkBitmap* bm) {
+ GrTexture* tex = image->getTexture();
+ if (tex) {
+ // TODO: handle the GrTexture directly, and skip GrPixelRef
+ const SkImageInfo info = make_info(tex, image->width(), image->height(), image->isOpaque());
+ bm->setInfo(info);
+ bm->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, tex)))->unref();
+ } else {
+ if (!as_IB(image)->getROPixels(bm)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void SkGpuDevice::drawImage(const SkDraw& draw, const SkImage* image, SkScalar x, SkScalar y,
+ const SkPaint& paint) {
+ SkBitmap bm;
+ if (wrap_as_bm(image, &bm)) {
+ this->drawBitmap(draw, bm, SkMatrix::MakeTrans(x, y), paint);
+ }
+}
+
+void SkGpuDevice::drawImageRect(const SkDraw& draw, const SkImage* image, const SkRect* src,
+ const SkRect& dst, const SkPaint& paint) {
+ SkBitmap bm;
+ if (wrap_as_bm(image, &bm)) {
+ this->drawBitmapRect(draw, bm, src, dst, paint, SkCanvas::kNone_DrawBitmapRectFlag);
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
// must be in SkCanvas::VertexMode order
diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h
index 30cf68daa8..89959e1f9c 100644
--- a/src/gpu/SkGpuDevice.h
+++ b/src/gpu/SkGpuDevice.h
@@ -115,6 +115,9 @@ public:
const SkPaint&) override;
virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
const SkPaint&) override;
+ void drawImage(const SkDraw&, const SkImage*, SkScalar x, SkScalar y, const SkPaint&) override;
+ void drawImageRect(const SkDraw&, const SkImage*, const SkRect* src, const SkRect& dst,
+ const SkPaint&) override;
void flush() override;
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index f427755d47..494e21004a 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -25,15 +25,6 @@ uint32_t SkImage::NextUniqueID() {
return id;
}
-void SkImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
- as_IB(this)->onDraw(canvas, x, y, paint);
-}
-
-void SkImage::drawRect(SkCanvas* canvas, const SkRect* src, const SkRect& dst,
- const SkPaint* paint) const {
- as_IB(this)->onDrawRect(canvas, src, dst, paint);
-}
-
const void* SkImage::peekPixels(SkImageInfo* info, size_t* rowBytes) const {
SkImageInfo infoStorage;
size_t rowBytesStorage;
diff --git a/src/image/SkImage_Base.h b/src/image/SkImage_Base.h
index 512c80c44b..5daf4195e2 100644
--- a/src/image/SkImage_Base.h
+++ b/src/image/SkImage_Base.h
@@ -36,9 +36,6 @@ public:
const SkSurfaceProps& props() const { return fProps; }
- virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const = 0;
- virtual void onDrawRect(SkCanvas*, const SkRect* src,
- const SkRect& dst, const SkPaint*) const = 0;
virtual SkSurface* onNewSurface(const SkImageInfo&, const SkSurfaceProps&) const = 0;
virtual const void* onPeekPixels(SkImageInfo*, size_t* /*rowBytes*/) const {
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index 7ccff17d9b..eec0d19760 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -26,15 +26,6 @@ SkShader* SkImage_Gpu::onNewShader(SkShader::TileMode tileX,
return SkShader::CreateBitmapShader(fBitmap, tileX, tileY, localMatrix);
}
-void SkImage_Gpu::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
- canvas->drawBitmap(fBitmap, x, y, paint);
-}
-
-void SkImage_Gpu::onDrawRect(SkCanvas* canvas, const SkRect* src, const SkRect& dst,
- const SkPaint* paint) const {
- canvas->drawBitmapRectToRect(fBitmap, src, dst, paint);
-}
-
SkSurface* SkImage_Gpu::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) const {
GrContext* ctx = this->getTexture()->getContext();
// TODO: Change signature of onNewSurface to take a budgeted param.
diff --git a/src/image/SkImage_Gpu.h b/src/image/SkImage_Gpu.h
index a771ddab24..7b38e60ea3 100644
--- a/src/image/SkImage_Gpu.h
+++ b/src/image/SkImage_Gpu.h
@@ -21,9 +21,6 @@ public:
SkImage_Gpu(const SkBitmap&, int sampleCountForNewSurfaces, SkSurface::Budgeted);
- void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const override;
- void onDrawRect(SkCanvas*, const SkRect* src, const SkRect& dst,
- const SkPaint*) const override;
SkSurface* onNewSurface(const SkImageInfo&, const SkSurfaceProps&) const override;
GrTexture* onGetTexture() const override;
bool getROPixels(SkBitmap*) const override;
diff --git a/src/image/SkImage_Raster.cpp b/src/image/SkImage_Raster.cpp
index acf805829d..20ae62c9f7 100644
--- a/src/image/SkImage_Raster.cpp
+++ b/src/image/SkImage_Raster.cpp
@@ -53,8 +53,6 @@ public:
SkImage_Raster(const SkImageInfo&, SkData*, size_t rb, const SkSurfaceProps*);
virtual ~SkImage_Raster();
- void onDraw(SkCanvas*, SkScalar, SkScalar, const SkPaint*) const override;
- void onDrawRect(SkCanvas*, const SkRect*, const SkRect&, const SkPaint*) const override;
SkSurface* onNewSurface(const SkImageInfo&, const SkSurfaceProps&) const override;
bool onReadPixels(const SkImageInfo&, void*, size_t, int srcX, int srcY) const override;
const void* onPeekPixels(SkImageInfo*, size_t* /*rowBytes*/) const override;
@@ -120,17 +118,6 @@ SkShader* SkImage_Raster::onNewShader(SkShader::TileMode tileX, SkShader::TileMo
return SkShader::CreateBitmapShader(fBitmap, tileX, tileY, localMatrix);
}
-void SkImage_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
- SkBitmap shallowCopy(fBitmap);
- canvas->drawBitmap(shallowCopy, x, y, paint);
-}
-
-void SkImage_Raster::onDrawRect(SkCanvas* canvas, const SkRect* src, const SkRect& dst,
- const SkPaint* paint) const {
- SkBitmap shallowCopy(fBitmap);
- canvas->drawBitmapRectToRect(shallowCopy, src, dst, paint);
-}
-
SkSurface* SkImage_Raster::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) const {
return SkSurface::NewRaster(info, &props);
}
diff --git a/src/pipe/SkGPipePriv.h b/src/pipe/SkGPipePriv.h
index 736930b652..c3919f635b 100644
--- a/src/pipe/SkGPipePriv.h
+++ b/src/pipe/SkGPipePriv.h
@@ -43,6 +43,8 @@ enum DrawOps {
kDrawBitmapNine_DrawOp,
kDrawBitmapRectToRect_DrawOp,
kDrawDRRect_DrawOp,
+ kDrawImage_DrawOp,
+ kDrawImageRect_DrawOp,
kDrawOval_DrawOp,
kDrawPaint_DrawOp,
kDrawPatch_DrawOp,
@@ -79,6 +81,7 @@ enum DrawOps {
// these are signals to playback, not drawing verbs
kReportFlags_DrawOp,
kShareBitmapHeap_DrawOp,
+ kShareImageHeap_DrawOp,
kDone_DrawOp,
};
@@ -141,6 +144,7 @@ enum {
kDrawVertices_HasIndices_DrawOpFlag = 1 << 2,
kDrawVertices_HasXfermode_DrawOpFlag = 1 << 3,
};
+// These are shared between drawbitmap and drawimage
enum {
kDrawBitmap_HasPaint_DrawOpFlag = 1 << 0,
// Specific to drawBitmapRect, but needs to be different from HasPaint,
@@ -213,6 +217,22 @@ static inline bool shouldFlattenBitmaps(uint32_t flags) {
&& !(flags & SkGPipeWriter::kSharedAddressSpace_Flag));
}
+class SkImageHeap : public SkRefCnt {
+public:
+ SkImageHeap();
+ virtual ~SkImageHeap();
+
+ // slot must be "valid" -- 0 is never valid
+ const SkImage* get(int32_t slot) const;
+ // returns 0 if not found, else returns slot
+ int32_t find(const SkImage*) const;
+ // returns non-zero value for where the image was stored
+ int32_t insert(const SkImage*);
+
+private:
+ SkTDArray<const SkImage*> fArray;
+};
+
///////////////////////////////////////////////////////////////////////////////
enum PaintOps {
diff --git a/src/pipe/SkGPipeRead.cpp b/src/pipe/SkGPipeRead.cpp
index f8411f5aea..917bb50976 100644
--- a/src/pipe/SkGPipeRead.cpp
+++ b/src/pipe/SkGPipeRead.cpp
@@ -178,6 +178,10 @@ public:
this->updateReader();
}
+ void setImageHeap(SkImageHeap* heap) {
+ fImageHeap.reset(SkRef(heap));
+ }
+
/**
* Access the shared heap. Only used in the case when bitmaps are not
* flattened.
@@ -198,6 +202,10 @@ public:
return id ? fTypefaces[id - 1] : NULL;
}
+ const SkImage* getImage(int32_t slot) const {
+ return fImageHeap->get(slot);
+ }
+
private:
void updateReader() {
if (NULL == fReader) {
@@ -227,6 +235,7 @@ private:
bool fSilent;
// Only used when sharing bitmaps with the writer.
SkBitmapHeap* fSharedHeap;
+ SkAutoTUnref<SkImageHeap> fImageHeap;
unsigned fFlags;
};
@@ -629,6 +638,35 @@ static void drawSprite_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
}
}
+static void drawImage_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32, SkGPipeState* state) {
+ unsigned slot = DrawOp_unpackData(op32);
+ unsigned flags = DrawOp_unpackFlags(op32);
+ bool hasPaint = SkToBool(flags & kDrawBitmap_HasPaint_DrawOpFlag);
+ SkScalar x = reader->readScalar();
+ SkScalar y = reader->readScalar();
+ const SkImage* image = state->getImage(slot);
+ if (state->shouldDraw()) {
+ canvas->drawImage(image, x, y, hasPaint ? &state->paint() : NULL);
+ }
+}
+
+static void drawImageRect_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
+ SkGPipeState* state) {
+ unsigned slot = DrawOp_unpackData(op32);
+ unsigned flags = DrawOp_unpackFlags(op32);
+ bool hasPaint = SkToBool(flags & kDrawBitmap_HasPaint_DrawOpFlag);
+ bool hasSrc = SkToBool(flags & kDrawBitmap_HasSrcRect_DrawOpFlag);
+ const SkRect* src = NULL;
+ if (hasSrc) {
+ src = skip<SkRect>(reader);
+ }
+ const SkRect* dst = skip<SkRect>(reader);
+ const SkImage* image = state->getImage(slot);
+ if (state->shouldDraw()) {
+ canvas->drawImageRect(image, src, *dst, hasPaint ? &state->paint() : NULL);
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
static void drawPicture_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
@@ -774,10 +812,14 @@ static void reportFlags_rp(SkCanvas*, SkReader32*, uint32_t op32,
}
static void shareBitmapHeap_rp(SkCanvas*, SkReader32* reader, uint32_t,
- SkGPipeState* state) {
+ SkGPipeState* state) {
state->setSharedHeap(static_cast<SkBitmapHeap*>(reader->readPtr()));
}
+static void shareImageHeap_rp(SkCanvas*, SkReader32* reader, uint32_t, SkGPipeState* state) {
+ state->setImageHeap(static_cast<SkImageHeap*>(reader->readPtr()));
+}
+
static void done_rp(SkCanvas*, SkReader32*, uint32_t, SkGPipeState*) {}
typedef void (*ReadProc)(SkCanvas*, SkReader32*, uint32_t op32, SkGPipeState*);
@@ -793,6 +835,8 @@ static const ReadProc gReadTable[] = {
drawBitmapNine_rp,
drawBitmapRect_rp,
drawDRRect_rp,
+ drawImage_rp,
+ drawImageRect_rp,
drawOval_rp,
drawPaint_rp,
drawPatch_rp,
@@ -828,6 +872,7 @@ static const ReadProc gReadTable[] = {
reportFlags_rp,
shareBitmapHeap_rp,
+ shareImageHeap_rp,
done_rp
};
diff --git a/src/pipe/SkGPipeWrite.cpp b/src/pipe/SkGPipeWrite.cpp
index 83e5c57d27..2e73be83f1 100644
--- a/src/pipe/SkGPipeWrite.cpp
+++ b/src/pipe/SkGPipeWrite.cpp
@@ -272,12 +272,9 @@ protected:
void onDrawBitmap(const SkBitmap&, SkScalar left, SkScalar top, const SkPaint*) override;
void onDrawBitmapRect(const SkBitmap&, const SkRect* src, const SkRect& dst, const SkPaint*,
DrawBitmapRectFlags flags) override;
-#if 0
- // rely on decomposition into bitmap (for now)
void onDrawImage(const SkImage*, SkScalar left, SkScalar top, const SkPaint*) override;
void onDrawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,
const SkPaint*) override;
-#endif
void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
const SkPaint*) override;
void onDrawSprite(const SkBitmap&, int left, int top, const SkPaint*) override;
@@ -300,6 +297,7 @@ private:
SkNamedFactorySet* fFactorySet;
SkBitmapHeap* fBitmapHeap;
+ SkImageHeap* fImageHeap;
SkGPipeController* fController;
SkWriter32& fWriter;
size_t fBlockSize; // amount allocated for writer
@@ -348,8 +346,8 @@ private:
// Common code used by drawBitmap*. Behaves differently depending on the
// type of SkBitmapHeap being used, which is determined by the flags used.
- bool commonDrawBitmap(const SkBitmap& bm, DrawOps op, unsigned flags,
- size_t opBytesNeeded, const SkPaint* paint);
+ bool commonDrawBitmap(const SkBitmap&, DrawOps, unsigned flags, size_t bytes, const SkPaint*);
+ bool commonDrawImage(const SkImage*, DrawOps, unsigned flags, size_t bytes, const SkPaint*);
SkPaint fPaint;
void writePaint(const SkPaint&);
@@ -462,6 +460,13 @@ SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller,
}
}
fFlattenableHeap.setBitmapStorage(fBitmapHeap);
+
+ fImageHeap = SkNEW(SkImageHeap);
+ if (this->needOpBytes(sizeof(void*))) {
+ this->writeOp(kShareImageHeap_DrawOp);
+ fWriter.writePtr(static_cast<void*>(fImageHeap));
+ }
+
this->doNotify();
}
@@ -469,6 +474,7 @@ SkGPipeCanvas::~SkGPipeCanvas() {
this->finish(true);
SkSafeUnref(fFactorySet);
SkSafeUnref(fBitmapHeap);
+ SkSafeUnref(fImageHeap);
}
bool SkGPipeCanvas::needOpBytes(size_t needed) {
@@ -823,6 +829,53 @@ void SkGPipeCanvas::onDrawSprite(const SkBitmap& bm, int left, int top, const Sk
}
}
+bool SkGPipeCanvas::commonDrawImage(const SkImage* image, DrawOps op, unsigned flags,
+ size_t opBytesNeeded, const SkPaint* paint) {
+ if (fDone) {
+ return false;
+ }
+
+ if (paint != NULL) {
+ flags |= kDrawBitmap_HasPaint_DrawOpFlag;
+ this->writePaint(*paint);
+ }
+ // This needs to run first so its calls to needOpBytes() and its writes
+ // don't interlace with the needOpBytes() and write below.
+ int32_t slot = fImageHeap->insert(image);
+ SkASSERT(slot != 0);
+ if (this->needOpBytes(opBytesNeeded)) {
+ this->writeOp(op, flags, slot);
+ return true;
+ }
+ return false;
+}
+
+void SkGPipeCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
+ const SkPaint* paint) {
+ NOTIFY_SETUP(this);
+ if (this->commonDrawImage(image, kDrawImage_DrawOp, 0, sizeof(SkScalar) * 2, paint)) {
+ fWriter.writeScalar(x);
+ fWriter.writeScalar(y);
+ }
+}
+
+void SkGPipeCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
+ const SkPaint* paint) {
+ NOTIFY_SETUP(this);
+ unsigned flags = 0;
+ size_t opBytesNeeded = sizeof(SkRect); // dst
+ if (src) {
+ flags |= kDrawBitmap_HasSrcRect_DrawOpFlag;
+ opBytesNeeded += sizeof(SkRect); // src
+ }
+ if (this->commonDrawImage(image, kDrawImageRect_DrawOp, flags, opBytesNeeded, paint)) {
+ if (src) {
+ fWriter.writeRect(*src);
+ }
+ fWriter.writeRect(dst);
+ }
+}
+
void SkGPipeCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
const SkPaint& paint) {
if (byteLength) {
@@ -1337,3 +1390,34 @@ void BitmapShuttle::removeCanvas() {
fCanvas->unref();
fCanvas = NULL;
}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+SkImageHeap::SkImageHeap() {}
+
+SkImageHeap::~SkImageHeap() {
+ fArray.unrefAll();
+}
+
+const SkImage* SkImageHeap::get(int32_t slot) const {
+ SkASSERT(slot > 0);
+ return fArray[slot - 1];
+}
+
+int32_t SkImageHeap::find(const SkImage* img) const {
+ int index = fArray.find(img);
+ if (index >= 0) {
+ return index + 1; // found
+ }
+ return 0; // not found
+}
+
+int32_t SkImageHeap::insert(const SkImage* img) {
+ int32_t slot = this->find(img);
+ if (slot) {
+ return slot;
+ }
+ *fArray.append() = SkRef(img);
+ return fArray.count(); // slot is always index+1
+}
+
diff --git a/src/utils/SkDeferredCanvas.cpp b/src/utils/SkDeferredCanvas.cpp
index d5cf97bd04..7d0a8e8593 100644
--- a/src/utils/SkDeferredCanvas.cpp
+++ b/src/utils/SkDeferredCanvas.cpp
@@ -32,12 +32,31 @@ enum PlaybackMode {
kSilent_PlaybackMode,
};
-static bool should_draw_immediately(const SkBitmap* bitmap, const SkPaint* paint,
- size_t bitmapSizeThreshold) {
+static uint64_t image_area(const SkImage* image) {
+ return sk_64_mul(image->width(), image->height());
+}
+
+// HACK -- see crbug.com/485243
+//
+// Work around case where Blink gives us an image, but will "mutate" it (by changing its contents
+// directly using webgl). Until that is fixed at the call-site, we treat gpu-backed-images as
+// mutable for now (at least for the purposes of deferred canvas)
+//
+static bool should_draw_gpu_image_immediately(const SkImage* image) {
+ return image->getTexture() != NULL;
+}
+
+static bool should_draw_immediately(const SkBitmap* bitmap, const SkImage* image,
+ const SkPaint* paint, size_t bitmapSizeThreshold) {
if (bitmap && ((bitmap->getTexture() && !bitmap->isImmutable()) ||
- (bitmap->getSize() > bitmapSizeThreshold))) {
+ (bitmap->getSize() > bitmapSizeThreshold))) {
return true;
}
+ if (image) {
+ if (should_draw_gpu_image_immediately(image) || image_area(image) > bitmapSizeThreshold) {
+ return true;
+ }
+ }
if (paint) {
SkShader* shader = paint->getShader();
// Here we detect the case where the shader is an SkBitmapProcShader
@@ -202,6 +221,11 @@ protected:
void drawSprite(const SkDraw&, const SkBitmap& bitmap,
int x, int y, const SkPaint& paint) override
{SkASSERT(0);}
+ void drawImage(const SkDraw&, const SkImage*, SkScalar, SkScalar, const SkPaint&) override
+ {SkASSERT(0);}
+ void drawImageRect(const SkDraw&, const SkImage*, const SkRect*, const SkRect&,
+ const SkPaint&) override
+ {SkASSERT(0);}
void drawText(const SkDraw&, const void* text, size_t len,
SkScalar x, SkScalar y, const SkPaint& paint) override
{SkASSERT(0);}
@@ -481,11 +505,15 @@ class AutoImmediateDrawIfNeeded {
public:
AutoImmediateDrawIfNeeded(SkDeferredCanvas& canvas, const SkBitmap* bitmap,
const SkPaint* paint) {
- this->init(canvas, bitmap, paint);
+ this->init(canvas, bitmap, NULL, paint);
+ }
+ AutoImmediateDrawIfNeeded(SkDeferredCanvas& canvas, const SkImage* image,
+ const SkPaint* paint) {
+ this->init(canvas, NULL, image, paint);
}
AutoImmediateDrawIfNeeded(SkDeferredCanvas& canvas, const SkPaint* paint) {
- this->init(canvas, NULL, paint);
+ this->init(canvas, NULL, NULL, paint);
}
~AutoImmediateDrawIfNeeded() {
@@ -494,9 +522,10 @@ public:
}
}
private:
- void init(SkDeferredCanvas& canvas, const SkBitmap* bitmap, const SkPaint* paint) {
+ void init(SkDeferredCanvas& canvas, const SkBitmap* bitmap, const SkImage* image,
+ const SkPaint* paint) {
if (canvas.isDeferredDrawing() &&
- should_draw_immediately(bitmap, paint, canvas.getBitmapSizeThreshold())) {
+ should_draw_immediately(bitmap, image, paint, canvas.getBitmapSizeThreshold())) {
canvas.setDeferredDrawing(false);
fCanvas = &canvas;
} else {
@@ -836,6 +865,34 @@ void SkDeferredCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* sr
this->recordedDrawCommand();
}
+
+void SkDeferredCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
+ const SkPaint* paint) {
+ SkRect bounds = SkRect::MakeXYWH(x, y,
+ SkIntToScalar(image->width()), SkIntToScalar(image->height()));
+ if (fDeferredDrawing &&
+ this->isFullFrame(&bounds, paint) &&
+ isPaintOpaque(paint, image)) {
+ this->getDeferredDevice()->skipPendingCommands();
+ }
+
+ AutoImmediateDrawIfNeeded autoDraw(*this, image, paint);
+ this->drawingCanvas()->drawImage(image, x, y, paint);
+ this->recordedDrawCommand();
+}
+void SkDeferredCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
+ const SkPaint* paint) {
+ if (fDeferredDrawing &&
+ this->isFullFrame(&dst, paint) &&
+ isPaintOpaque(paint, image)) {
+ this->getDeferredDevice()->skipPendingCommands();
+ }
+
+ AutoImmediateDrawIfNeeded autoDraw(*this, image, paint);
+ this->drawingCanvas()->drawImageRect(image, src, dst, paint);
+ this->recordedDrawCommand();
+}
+
void SkDeferredCanvas::onDrawBitmapNine(const SkBitmap& bitmap,
const SkIRect& center, const SkRect& dst,
const SkPaint* paint) {