add SkImage::newSurface

BUG=skia:

Review URL: https://codereview.chromium.org/741763002
This commit is contained in:
reed 2014-11-21 08:46:37 -08:00 committed by Commit bot
parent 41d2c2e434
commit 4af267b119
13 changed files with 189 additions and 56 deletions

View File

@ -105,5 +105,55 @@ protected:
private:
typedef GM INHERITED;
};
DEF_GM( return new SurfacePropsGM )
#ifdef SK_DEBUG
static bool equal(const SkSurfaceProps& a, const SkSurfaceProps& b) {
return a.flags() == b.flags() && a.pixelGeometry() == b.pixelGeometry();
}
#endif
class NewSurfaceGM : public skiagm::GM {
public:
NewSurfaceGM() {}
protected:
SkString onShortName() SK_OVERRIDE {
return SkString("surfacenew");
}
virtual SkISize onISize() SK_OVERRIDE {
return SkISize::Make(300, 140);
}
static void drawInto(SkCanvas* canvas) {
canvas->drawColor(SK_ColorRED);
}
virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
SkAutoTUnref<SkSurface> surf(canvas->newSurface(info, NULL));
if (!surf.get()) {
surf.reset(SkSurface::NewRaster(info));
}
drawInto(surf->getCanvas());
SkAutoTUnref<SkImage> image(surf->newImageSnapshot());
canvas->drawImage(image, 10, 10, NULL);
SkAutoTUnref<SkSurface> surf2(image->newSurface(info, NULL));
drawInto(surf2->getCanvas());
// Assert that the props were communicated transitively through the first image
SkASSERT(equal(surf->props(), surf2->props()));
SkAutoTUnref<SkImage> image2(surf2->newImageSnapshot());
canvas->drawImage(image2, 10 + SkIntToScalar(image->width()) + 10, 10, NULL);
}
private:
typedef GM INHERITED;
};
DEF_GM( return new NewSurfaceGM )

View File

@ -18,6 +18,8 @@ class SkData;
class SkCanvas;
class SkImageGenerator;
class SkPaint;
class SkSurface;
class SkSurfaceProps;
class GrContext;
class GrTexture;
@ -92,6 +94,15 @@ public:
SkData* encode(SkImageEncoder::Type t = SkImageEncoder::kPNG_Type,
int quality = 80) const;
/**
* Return a new surface that is compatible with this image's internal representation
* (e.g. raster or gpu).
*
* If no surfaceprops are specified, the image will attempt to match the props of when it
* was created (if it came from a surface).
*/
SkSurface* newSurface(const SkImageInfo&, const SkSurfaceProps* = NULL) const;
protected:
SkImage(int width, int height) :
fWidth(width),

View File

@ -62,6 +62,7 @@ public:
};
SkSurfaceProps(InitType);
SkSurfaceProps(uint32_t flags, InitType);
SkSurfaceProps(const SkSurfaceProps& other);
uint32_t flags() const { return fFlags; }
SkPixelGeometry pixelGeometry() const { return fPixelGeometry; }

View File

@ -9,14 +9,7 @@
#include "SkCanvas.h"
#include "SkImagePriv.h"
#include "SkImage_Base.h"
static SkImage_Base* as_IB(SkImage* image) {
return static_cast<SkImage_Base*>(image);
}
static const SkImage_Base* as_IB(const SkImage* image) {
return static_cast<const SkImage_Base*>(image);
}
#include "SkSurface.h"
uint32_t SkImage::NextUniqueID() {
static int32_t gUniqueID;
@ -91,6 +84,13 @@ SkData* SkImage::encode(SkImageEncoder::Type type, int quality) const {
return NULL;
}
SkSurface* SkImage::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) const {
if (NULL == props) {
props = &as_IB(this)->props();
}
return as_IB(this)->onNewSurface(info, *props);
}
///////////////////////////////////////////////////////////////////////////////
static bool raster_canvas_supports(const SkImageInfo& info) {

View File

@ -6,10 +6,12 @@
*/
#include "SkImagePriv.h"
#include "SkImage_Base.h"
#include "SkCanvas.h"
#include "SkPicture.h"
SkImage* SkNewImageFromBitmap(const SkBitmap& bm, bool canSharePixelRef) {
SkImage* SkNewImageFromBitmap(const SkBitmap& bm, bool canSharePixelRef,
const SkSurfaceProps* props) {
const SkImageInfo info = bm.info();
if (kUnknown_SkColorType == info.colorType()) {
return NULL;
@ -17,13 +19,18 @@ SkImage* SkNewImageFromBitmap(const SkBitmap& bm, bool canSharePixelRef) {
SkImage* image = NULL;
if (canSharePixelRef || bm.isImmutable()) {
image = SkNewImageFromPixelRef(info, bm.pixelRef(), bm.rowBytes());
image = SkNewImageFromPixelRef(info, bm.pixelRef(), bm.rowBytes(), props);
} else {
bm.lockPixels();
if (bm.getPixels()) {
image = SkImage::NewRasterCopy(info, bm.getPixels(), bm.rowBytes());
}
bm.unlockPixels();
// we don't expose props to NewRasterCopy (need a private vers) so post-init it here
if (image && props) {
as_IB(image)->initWithProps(*props);
}
}
return image;
}

View File

@ -11,8 +11,8 @@
#include "SkImage.h"
// Call this if you explicitly want to use/share this pixelRef in the image
extern SkImage* SkNewImageFromPixelRef(const SkImageInfo&, SkPixelRef*,
size_t rowBytes);
extern SkImage* SkNewImageFromPixelRef(const SkImageInfo&, SkPixelRef*, size_t rowBytes,
const SkSurfaceProps*);
/**
* Examines the bitmap to decide if it can share the existing pixelRef, or
@ -24,7 +24,7 @@ extern SkImage* SkNewImageFromPixelRef(const SkImageInfo&, SkPixelRef*,
* SkImageInfo, or the bitmap's pixels cannot be accessed, this will return
* NULL.
*/
extern SkImage* SkNewImageFromBitmap(const SkBitmap&, bool canSharePixelRef);
extern SkImage* SkNewImageFromBitmap(const SkBitmap&, bool canSharePixelRef, const SkSurfaceProps*);
static inline size_t SkImageMinRowBytes(const SkImageInfo& info) {
return SkAlign4(info.minRowBytes());
@ -45,4 +45,6 @@ extern GrTexture* SkTextureImageGetTexture(SkImage* textureImage);
// surface needs to perform a copy-on-write
extern void SkTextureImageSetTexture(SkImage* image, GrTexture* texture);
extern SkImage* SkNewImageFromBitmapTexture(const SkBitmap&, int sampleCount);
#endif

View File

@ -9,14 +9,37 @@
#define SkImage_Base_DEFINED
#include "SkImage.h"
#include "SkSurface.h"
static SkSurfaceProps copy_or_safe_defaults(const SkSurfaceProps* props) {
return props ? *props : SkSurfaceProps(0, kUnknown_SkPixelGeometry);
}
class SkImage_Base : public SkImage {
public:
SkImage_Base(int width, int height) : INHERITED(width, height) {}
SkImage_Base(int width, int height, const SkSurfaceProps* props)
: INHERITED(width, height)
, fProps(copy_or_safe_defaults(props))
{}
/**
* If the props weren't know at constructor time, call this but only before the image is
* ever released into the wild (since the props field must appear to be immutable).
*/
void initWithProps(const SkSurfaceProps& props) {
SkASSERT(this->unique()); // only viewed by one thread
SkSurfaceProps* mutableProps = const_cast<SkSurfaceProps*>(&fProps);
SkASSERT(mutableProps != &props); // check for self-assignment
mutableProps->~SkSurfaceProps();
new (mutableProps) SkSurfaceProps(props);
}
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;
// Default impl calls onDraw
virtual bool onReadPixels(SkBitmap*, const SkIRect& subset) const;
@ -34,8 +57,19 @@ public:
virtual SkShader* onNewShader(SkShader::TileMode,
SkShader::TileMode,
const SkMatrix* localMatrix) const { return NULL; };
private:
const SkSurfaceProps fProps;
typedef SkImage INHERITED;
};
static inline SkImage_Base* as_IB(SkImage* image) {
return static_cast<SkImage_Base*>(image);
}
static inline const SkImage_Base* as_IB(const SkImage* image) {
return static_cast<const SkImage_Base*>(image);
}
#endif

View File

@ -9,6 +9,7 @@
#include "SkImagePriv.h"
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkSurface.h"
#include "GrContext.h"
#include "GrTexture.h"
@ -16,40 +17,40 @@ class SkImage_Gpu : public SkImage_Base {
public:
SK_DECLARE_INST_COUNT(SkImage_Gpu)
explicit SkImage_Gpu(const SkBitmap&);
virtual ~SkImage_Gpu();
SkImage_Gpu(const SkBitmap&, int sampleCount);
virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const SK_OVERRIDE;
virtual void onDrawRect(SkCanvas*, const SkRect* src, const SkRect& dst,
const SkPaint*) const SK_OVERRIDE;
virtual GrTexture* onGetTexture() const SK_OVERRIDE;
virtual bool getROPixels(SkBitmap*) const SK_OVERRIDE;
void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const SK_OVERRIDE;
void onDrawRect(SkCanvas*, const SkRect* src, const SkRect& dst,
const SkPaint*) const SK_OVERRIDE;
SkSurface* onNewSurface(const SkImageInfo&, const SkSurfaceProps&) const SK_OVERRIDE;
GrTexture* onGetTexture() const SK_OVERRIDE;
bool getROPixels(SkBitmap*) const SK_OVERRIDE;
GrTexture* getTexture() const { return fBitmap.getTexture(); }
virtual SkShader* onNewShader(SkShader::TileMode,
SkShader* onNewShader(SkShader::TileMode,
SkShader::TileMode,
const SkMatrix* localMatrix) const SK_OVERRIDE;
virtual bool isOpaque() const SK_OVERRIDE;
bool isOpaque() const SK_OVERRIDE;
private:
SkBitmap fBitmap;
const int fSampleCount; // 0 if we weren't built from a surface
typedef SkImage_Base INHERITED;
};
///////////////////////////////////////////////////////////////////////////////
SkImage_Gpu::SkImage_Gpu(const SkBitmap& bitmap)
: INHERITED(bitmap.width(), bitmap.height())
, fBitmap(bitmap) {
SkImage_Gpu::SkImage_Gpu(const SkBitmap& bitmap, int sampleCount)
: INHERITED(bitmap.width(), bitmap.height(), NULL)
, fBitmap(bitmap)
, fSampleCount(sampleCount)
{
SkASSERT(fBitmap.getTexture());
}
SkImage_Gpu::~SkImage_Gpu() {
}
SkShader* SkImage_Gpu::onNewShader(SkShader::TileMode tileX,
SkShader::TileMode tileY,
const SkMatrix* localMatrix) const
@ -66,6 +67,11 @@ void SkImage_Gpu::onDrawRect(SkCanvas* canvas, const SkRect* src, const SkRect&
canvas->drawBitmapRectToRect(fBitmap, src, dst, paint);
}
SkSurface* SkImage_Gpu::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) const {
GrContext* ctx = this->getTexture()->getContext();
return SkSurface::NewRenderTarget(ctx, info, fSampleCount, &props);
}
GrTexture* SkImage_Gpu::onGetTexture() const {
return fBitmap.getTexture();
}
@ -80,14 +86,18 @@ bool SkImage_Gpu::isOpaque() const {
///////////////////////////////////////////////////////////////////////////////
SkImage* SkImage::NewTexture(const SkBitmap& bitmap) {
SkImage* SkNewImageFromBitmapTexture(const SkBitmap& bitmap, int sampleCount) {
if (NULL == bitmap.getTexture()) {
return NULL;
}
return SkNEW_ARGS(SkImage_Gpu, (bitmap, sampleCount));
}
return SkNEW_ARGS(SkImage_Gpu, (bitmap));
SkImage* SkImage::NewTexture(const SkBitmap& bitmap) {
return SkNewImageFromBitmapTexture(bitmap, 0);
}
GrTexture* SkTextureImageGetTexture(SkImage* image) {
return ((SkImage_Gpu*)image)->getTexture();
}

View File

@ -11,6 +11,7 @@
#include "SkCanvas.h"
#include "SkData.h"
#include "SkDecodingImageGenerator.h"
#include "SkSurface.h"
class SkImage_Raster : public SkImage_Base {
public:
@ -50,18 +51,18 @@ public:
static SkImage* NewEmpty();
SkImage_Raster(const SkImageInfo&, SkData*, size_t rb);
SkImage_Raster(const SkImageInfo&, SkData*, size_t rb, const SkSurfaceProps*);
virtual ~SkImage_Raster();
virtual void onDraw(SkCanvas*, SkScalar, SkScalar, const SkPaint*) const SK_OVERRIDE;
virtual void onDrawRect(SkCanvas*, const SkRect*, const SkRect&,
const SkPaint*) const SK_OVERRIDE;
virtual bool onReadPixels(SkBitmap*, const SkIRect&) const SK_OVERRIDE;
virtual const void* onPeekPixels(SkImageInfo*, size_t* /*rowBytes*/) const SK_OVERRIDE;
virtual bool getROPixels(SkBitmap*) const SK_OVERRIDE;
void onDraw(SkCanvas*, SkScalar, SkScalar, const SkPaint*) const SK_OVERRIDE;
void onDrawRect(SkCanvas*, const SkRect*, const SkRect&, const SkPaint*) const SK_OVERRIDE;
SkSurface* onNewSurface(const SkImageInfo&, const SkSurfaceProps&) const SK_OVERRIDE;
bool onReadPixels(SkBitmap*, const SkIRect&) const SK_OVERRIDE;
const void* onPeekPixels(SkImageInfo*, size_t* /*rowBytes*/) const SK_OVERRIDE;
bool getROPixels(SkBitmap*) const SK_OVERRIDE;
// exposed for SkSurface_Raster via SkNewImageFromPixelRef
SkImage_Raster(const SkImageInfo&, SkPixelRef*, size_t rowBytes);
SkImage_Raster(const SkImageInfo&, SkPixelRef*, size_t rowBytes, const SkSurfaceProps*);
SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); }
@ -71,12 +72,12 @@ public:
virtual bool isOpaque() const SK_OVERRIDE;
SkImage_Raster(const SkBitmap& bm)
: INHERITED(bm.width(), bm.height())
SkImage_Raster(const SkBitmap& bm, const SkSurfaceProps* props)
: INHERITED(bm.width(), bm.height(), props)
, fBitmap(bm) {}
private:
SkImage_Raster() : INHERITED(0, 0) {}
SkImage_Raster() : INHERITED(0, 0, NULL) {}
SkBitmap fBitmap;
@ -100,8 +101,9 @@ static void release_data(void* addr, void* context) {
data->unref();
}
SkImage_Raster::SkImage_Raster(const Info& info, SkData* data, size_t rowBytes)
: INHERITED(info.width(), info.height())
SkImage_Raster::SkImage_Raster(const Info& info, SkData* data, size_t rowBytes,
const SkSurfaceProps* props)
: INHERITED(info.width(), info.height(), props)
{
data->ref();
void* addr = const_cast<void*>(data->data());
@ -112,8 +114,9 @@ SkImage_Raster::SkImage_Raster(const Info& info, SkData* data, size_t rowBytes)
fBitmap.lockPixels();
}
SkImage_Raster::SkImage_Raster(const Info& info, SkPixelRef* pr, size_t rowBytes)
: INHERITED(info.width(), info.height())
SkImage_Raster::SkImage_Raster(const Info& info, SkPixelRef* pr, size_t rowBytes,
const SkSurfaceProps* props)
: INHERITED(info.width(), info.height(), props)
{
fBitmap.setInfo(info, rowBytes);
fBitmap.setPixelRef(pr);
@ -136,6 +139,10 @@ void SkImage_Raster::onDrawRect(SkCanvas* canvas, const SkRect* src, const SkRec
canvas->drawBitmapRectToRect(fBitmap, src, dst, paint);
}
SkSurface* SkImage_Raster::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) const {
return SkSurface::NewRaster(info, &props);
}
bool SkImage_Raster::onReadPixels(SkBitmap* dst, const SkIRect& subset) const {
if (dst->pixelRef()) {
return this->INHERITED::onReadPixels(dst, subset);
@ -179,7 +186,7 @@ SkImage* SkImage::NewRasterCopy(const SkImageInfo& info, const void* pixels, siz
// Here we actually make a copy of the caller's pixel data
SkAutoDataUnref data(SkData::NewWithCopy(pixels, info.height() * rowBytes));
return SkNEW_ARGS(SkImage_Raster, (info, data, rowBytes));
return SkNEW_ARGS(SkImage_Raster, (info, data, rowBytes, NULL));
}
@ -201,7 +208,7 @@ SkImage* SkImage::NewRasterData(const SkImageInfo& info, SkData* data, size_t ro
return NULL;
}
return SkNEW_ARGS(SkImage_Raster, (info, data, rowBytes));
return SkNEW_ARGS(SkImage_Raster, (info, data, rowBytes, NULL));
}
SkImage* SkImage::NewFromGenerator(SkImageGenerator* generator) {
@ -209,12 +216,12 @@ SkImage* SkImage::NewFromGenerator(SkImageGenerator* generator) {
if (!SkInstallDiscardablePixelRef(generator, &bitmap)) {
return NULL;
}
return SkNEW_ARGS(SkImage_Raster, (bitmap));
return SkNEW_ARGS(SkImage_Raster, (bitmap, NULL));
}
SkImage* SkNewImageFromPixelRef(const SkImageInfo& info, SkPixelRef* pr,
size_t rowBytes) {
return SkNEW_ARGS(SkImage_Raster, (info, pr, rowBytes));
SkImage* SkNewImageFromPixelRef(const SkImageInfo& info, SkPixelRef* pr, size_t rowBytes,
const SkSurfaceProps* props) {
return SkNEW_ARGS(SkImage_Raster, (info, pr, rowBytes, props));
}
const SkPixelRef* SkBitmapImageGetPixelRef(const SkImage* image) {

View File

@ -47,6 +47,11 @@ SkSurfaceProps::SkSurfaceProps(uint32_t flags, SkPixelGeometry pg)
: fFlags(flags), fPixelGeometry(pg)
{}
SkSurfaceProps::SkSurfaceProps(const SkSurfaceProps& other)
: fFlags(other.fFlags)
, fPixelGeometry(other.fPixelGeometry)
{}
///////////////////////////////////////////////////////////////////////////////
SkSurface_Base::SkSurface_Base(int width, int height, const SkSurfaceProps* props)

View File

@ -7,6 +7,7 @@
#include "SkSurface_Base.h"
#include "SkImagePriv.h"
#include "SkImage_Base.h"
#include "SkCanvas.h"
#include "SkGpuDevice.h"
@ -66,7 +67,12 @@ SkSurface* SkSurface_Gpu::onNewSurface(const SkImageInfo& info) {
}
SkImage* SkSurface_Gpu::onNewImageSnapshot() {
return SkImage::NewTexture(fDevice->accessBitmap(false));
const int sampleCount = fDevice->accessRenderTarget()->numSamples();
SkImage* image = SkNewImageFromBitmapTexture(fDevice->accessBitmap(false), sampleCount);
if (image) {
as_IB(image)->initWithProps(this->props());
}
return image;
}
void SkSurface_Gpu::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,

View File

@ -115,7 +115,7 @@ void SkSurface_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
}
SkImage* SkSurface_Raster::onNewImageSnapshot() {
return SkNewImageFromBitmap(fBitmap, fWeOwnThePixels);
return SkNewImageFromBitmap(fBitmap, fWeOwnThePixels, &this->props());
}
void SkSurface_Raster::onCopyOnWrite(ContentChangeMode mode) {

View File

@ -65,7 +65,7 @@ public:
}
virtual SkImage* onNewImageSnapshot() SK_OVERRIDE {
return SkNewImageFromBitmap(fBitmap, true);
return SkNewImageFromBitmap(fBitmap, true, &this->props());
}
virtual void onCopyOnWrite(ContentChangeMode mode) SK_OVERRIDE {