Bug 722217; keep only a single snapshot. r=jrmuizel

This commit is contained in:
Nicholas Cameron 2012-09-06 16:07:53 +12:00
parent d6a99a40e3
commit 683496a28c
4 changed files with 24 additions and 57 deletions

View File

@ -297,7 +297,7 @@ DrawTargetCairo::DrawTargetCairo()
DrawTargetCairo::~DrawTargetCairo()
{
MarkSnapshotsIndependent();
MarkSnapshotIndependent();
if (mPathObserver) {
mPathObserver->ForgetDrawTarget();
}
@ -316,14 +316,18 @@ DrawTargetCairo::GetSize()
TemporaryRef<SourceSurface>
DrawTargetCairo::Snapshot()
{
if (mSnapshot) {
return mSnapshot;
}
IntSize size = GetSize();
cairo_content_t content = cairo_surface_get_content(mSurface);
RefPtr<SourceSurfaceCairo> surf = new SourceSurfaceCairo(mSurface, size,
CairoContentToGfxFormat(content),
this);
AppendSnapshot(surf);
return surf;
mSnapshot = new SourceSurfaceCairo(mSurface,
size,
CairoContentToGfxFormat(content),
this);
return mSnapshot;
}
void
@ -868,45 +872,21 @@ DrawTargetCairo::GetNativeSurface(NativeSurfaceType aType)
}
void
DrawTargetCairo::MarkSnapshotsIndependent()
DrawTargetCairo::MarkSnapshotIndependent()
{
// Make a copy of the vector, since MarkIndependent implicitly modifies mSnapshots.
std::vector<SourceSurfaceCairo*> snapshots = mSnapshots;
for (std::vector<SourceSurfaceCairo*>::iterator iter = snapshots.begin();
iter != snapshots.end();
++iter) {
(*iter)->MarkIndependent();
}
}
void
DrawTargetCairo::AppendSnapshot(SourceSurfaceCairo* aSnapshot)
{
mSnapshots.push_back(aSnapshot);
}
void
DrawTargetCairo::RemoveSnapshot(SourceSurfaceCairo* aSnapshot)
{
std::vector<SourceSurfaceCairo*>::iterator iter = std::find(mSnapshots.begin(),
mSnapshots.end(),
aSnapshot);
if (iter != mSnapshots.end()) {
mSnapshots.erase(iter);
if (mSnapshot) {
if (mSnapshot->refCount() > 1) {
// We only need to worry about snapshots that someone else knows about
mSnapshot->DrawTargetWillChange();
}
mSnapshot = nullptr;
}
}
void
DrawTargetCairo::WillChange(const Path* aPath /* = nullptr */)
{
if (!mSnapshots.empty()) {
for (std::vector<SourceSurfaceCairo*>::iterator iter = mSnapshots.begin();
iter != mSnapshots.end(); ++iter) {
(*iter)->DrawTargetWillChange();
}
// All snapshots will now have copied data.
mSnapshots.clear();
}
MarkSnapshotIndependent();
if (mPathObserver &&
(!aPath || !mPathObserver->ContainsPath(aPath))) {

View File

@ -147,19 +147,14 @@ private: // methods
const DrawOptions& aOptions,
DrawPatternType aDrawType);
// Copy-on-write support for snapshot surfaces.
friend class SourceSurfaceCairo;
void AppendSnapshot(SourceSurfaceCairo* aSnapshot);
void RemoveSnapshot(SourceSurfaceCairo* aSnapshot);
// Call before you make any changes to the backing surface with which this
// context is associated. Pass the path you're going to be using if you have
// one.
void WillChange(const Path* aPath = nullptr);
// Call if there is any reason to disassociate all snapshots from this draw
// Call if there is any reason to disassociate the snapshot from this draw
// target; for example, because we're going to be destroyed.
void MarkSnapshotsIndependent();
void MarkSnapshotIndependent();
// If the current operator is "source" then clear the destination before we
// draw into it, to simulate the effect of an unbounded source operator.
@ -168,7 +163,10 @@ private: // data
cairo_t* mContext;
cairo_surface_t* mSurface;
IntSize mSize;
std::vector<SourceSurfaceCairo*> mSnapshots;
// The latest snapshot of this surface. This needs to be told when this
// target is modified. We keep it alive as a cache.
RefPtr<SourceSurfaceCairo> mSnapshot;
// It is safe to use a regular pointer here because the CairoPathContext will
// deregister itself on destruction. Using a RefPtr would extend the life-

View File

@ -42,7 +42,6 @@ SourceSurfaceCairo::SourceSurfaceCairo(cairo_surface_t* aSurface,
SourceSurfaceCairo::~SourceSurfaceCairo()
{
MarkIndependent();
cairo_surface_destroy(mSurface);
}
@ -111,15 +110,6 @@ SourceSurfaceCairo::DrawTargetWillChange()
}
}
void
SourceSurfaceCairo::MarkIndependent()
{
if (mDrawTarget) {
mDrawTarget->RemoveSnapshot(this);
mDrawTarget = nullptr;
}
}
DataSourceSurfaceCairo::DataSourceSurfaceCairo(cairo_surface_t* imageSurf)
: mImageSurface(imageSurf)
{

View File

@ -36,7 +36,6 @@ public:
private: // methods
friend class DrawTargetCairo;
void DrawTargetWillChange();
void MarkIndependent();
private: // data
IntSize mSize;