Bug 688368 - Make SourceSurfaceSkia data surfaces copy-on-write. r=joe

This commit is contained in:
Matt Woodrow 2011-11-03 08:55:03 +13:00
parent 20deb50620
commit f3a5978660
4 changed files with 101 additions and 9 deletions

View File

@ -201,16 +201,17 @@ DrawTargetSkia::DrawTargetSkia()
DrawTargetSkia::~DrawTargetSkia()
{
MarkChanged();
}
TemporaryRef<SourceSurface>
DrawTargetSkia::Snapshot()
{
//TODO: Wrong! Copy the pixels, preferably lazily
RefPtr<SourceSurfaceSkia> source = new SourceSurfaceSkia();
if (!source->InitWithBitmap(mCanvas.get(), mFormat)) {
if (!source->InitWithBitmap(mBitmap, mFormat, this)) {
return NULL;
}
AppendSnapshot(source);
return source;
}
@ -383,6 +384,8 @@ DrawTargetSkia::DrawSurface(SourceSurface *aSurface,
return;
}
MarkChanged();
NS_ASSERTION(aSurfOptions.mFilter == FILTER_LINEAR, "Only linear filtering supported currently!");
SkRect destRect = RectToSkRect(aDest);
SkRect sourceRect = RectToSkRect(aSource);
@ -407,6 +410,7 @@ DrawTargetSkia::DrawSurfaceWithShadow(SourceSurface *aSurface,
Float aSigma,
CompositionOp aOperator)
{
MarkChanged();
mCanvas->save(SkCanvas::kMatrix_SaveFlag);
mCanvas->resetMatrix();
@ -466,6 +470,7 @@ DrawTargetSkia::FillRect(const Rect &aRect,
const Pattern &aPattern,
const DrawOptions &aOptions)
{
MarkChanged();
SkRect rect = RectToSkRect(aRect);
AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
@ -478,6 +483,7 @@ DrawTargetSkia::Stroke(const Path *aPath,
const StrokeOptions &aStrokeOptions,
const DrawOptions &aOptions)
{
MarkChanged();
if (aPath->GetBackendType() != BACKEND_SKIA) {
return;
}
@ -497,6 +503,7 @@ DrawTargetSkia::StrokeRect(const Rect &aRect,
const StrokeOptions &aStrokeOptions,
const DrawOptions &aOptions)
{
MarkChanged();
AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
paint.SetStroke(aStrokeOptions);
@ -510,6 +517,7 @@ DrawTargetSkia::StrokeLine(const Point &aStart,
const StrokeOptions &aStrokeOptions,
const DrawOptions &aOptions)
{
MarkChanged();
AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
paint.SetStroke(aStrokeOptions);
@ -523,6 +531,7 @@ DrawTargetSkia::Fill(const Path *aPath,
const Pattern &aPattern,
const DrawOptions &aOptions)
{
MarkChanged();
if (aPath->GetBackendType() != BACKEND_SKIA) {
return;
}
@ -544,6 +553,8 @@ DrawTargetSkia::FillGlyphs(ScaledFont *aFont,
return;
}
MarkChanged();
ScaledFontSkia* skiaFont = static_cast<ScaledFontSkia*>(aFont);
AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
@ -613,6 +624,8 @@ DrawTargetSkia::CopySurface(SourceSurface *aSurface,
if (aSurface->GetType() != SURFACE_SKIA) {
return;
}
MarkChanged();
const SkBitmap& bitmap = static_cast<SourceSurfaceSkia*>(aSurface)->GetBitmap();
@ -664,6 +677,7 @@ DrawTargetSkia::CreatePathBuilder(FillRule aFillRule) const
void
DrawTargetSkia::ClearRect(const Rect &aRect)
{
MarkChanged();
SkPaint paint;
mCanvas->save();
mCanvas->clipRect(RectToSkRect(aRect), SkRegion::kIntersect_Op);
@ -704,5 +718,33 @@ DrawTargetSkia::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops) co
return new GradientStopsSkia(stops, aNumStops);
}
void
DrawTargetSkia::AppendSnapshot(SourceSurfaceSkia* aSnapshot)
{
mSnapshots.push_back(aSnapshot);
}
void
DrawTargetSkia::RemoveSnapshot(SourceSurfaceSkia* aSnapshot)
{
std::vector<SourceSurfaceSkia*>::iterator iter = std::find(mSnapshots.begin(), mSnapshots.end(), aSnapshot);
if (iter != mSnapshots.end()) {
mSnapshots.erase(iter);
}
}
void
DrawTargetSkia::MarkChanged()
{
if (mSnapshots.size()) {
for (std::vector<SourceSurfaceSkia*>::iterator iter = mSnapshots.begin();
iter != mSnapshots.end(); iter++) {
(*iter)->DrawTargetWillChange();
}
// All snapshots will now have copied data.
mSnapshots.clear();
}
}
}
}

View File

@ -42,12 +42,15 @@
#include "Rect.h"
#include "PathSkia.h"
#include <sstream>
#include <vector>
using namespace std;
#include "gfxImageSurface.h"
namespace mozilla {
namespace gfx {
class SourceSurfaceSkia;
class DrawTargetSkia : public DrawTarget
{
public:
@ -119,6 +122,11 @@ public:
return stream.str();
}
private:
friend class SourceSurfaceSkia;
void AppendSnapshot(SourceSurfaceSkia* aSnapshot);
void RemoveSnapshot(SourceSurfaceSkia* aSnapshot);
void MarkChanged();
IntSize mSize;
SkBitmap mBitmap;
@ -126,6 +134,7 @@ private:
SkRefPtr<SkDevice> mDevice;
nsRefPtr<gfxImageSurface> mImageSurface;
SurfaceFormat mFormat;
vector<SourceSurfaceSkia*> mSnapshots;
};
}

View File

@ -41,16 +41,19 @@
#include "skia/SkBitmap.h"
#include "skia/SkDevice.h"
#include "HelpersSkia.h"
#include "DrawTargetSkia.h"
namespace mozilla {
namespace gfx {
SourceSurfaceSkia::SourceSurfaceSkia()
: mDrawTarget(NULL)
{
}
SourceSurfaceSkia::~SourceSurfaceSkia()
{
MarkIndependent();
}
IntSize
@ -86,13 +89,20 @@ SourceSurfaceSkia::InitFromData(unsigned char* aData,
}
bool
SourceSurfaceSkia::InitWithBitmap(SkCanvas* aBitmap,
SurfaceFormat aFormat)
SourceSurfaceSkia::InitWithBitmap(const SkBitmap& aBitmap,
SurfaceFormat aFormat,
DrawTargetSkia* aOwner)
{
if (aBitmap->readPixels(&mBitmap)) {
mFormat = aFormat;
mSize = IntSize(aBitmap.width(), aBitmap.height());
if (aOwner) {
mBitmap = aBitmap;
mStride = aBitmap.rowBytes();
mDrawTarget = aOwner;
return true;
} else if (aBitmap.copyTo(&mBitmap, aBitmap.getConfig())) {
mStride = mBitmap.rowBytes();
mSize = IntSize(mBitmap.width(), mBitmap.height());
mFormat = aFormat;
return true;
}
return false;
@ -108,6 +118,26 @@ SourceSurfaceSkia::GetData()
}
void
SourceSurfaceSkia::DrawTargetWillChange()
{
if (mDrawTarget) {
mDrawTarget = NULL;
SkBitmap temp = mBitmap;
mBitmap.reset();
temp.copyTo(&mBitmap, temp.getConfig());
}
}
void
SourceSurfaceSkia::MarkIndependent()
{
if (mDrawTarget) {
mDrawTarget->RemoveSnapshot(this);
mDrawTarget = NULL;
}
}
}
}

View File

@ -46,6 +46,8 @@
namespace mozilla {
namespace gfx {
class DrawTargetSkia;
class SourceSurfaceSkia : public DataSourceSurface
{
public:
@ -63,8 +65,13 @@ public:
int32_t aStride,
SurfaceFormat aFormat);
bool InitWithBitmap(SkCanvas* aBitmap,
SurfaceFormat aFormat);
/**
* If aOwner is NULL, we make a copy of the pixel data in the bitmap,
* otherwise we just reference this data until DrawTargetWillChange is called.
*/
bool InitWithBitmap(const SkBitmap& aBitmap,
SurfaceFormat aFormat,
DrawTargetSkia* aOwner);
virtual unsigned char *GetData();
@ -74,10 +81,14 @@ public:
private:
friend class DrawTargetSkia;
void DrawTargetWillChange();
void MarkIndependent();
SkBitmap mBitmap;
SurfaceFormat mFormat;
IntSize mSize;
int32_t mStride;
DrawTargetSkia* mDrawTarget;
};
}