From 2999f08ed4cbf1992548be987b15e2f8b71aaec7 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Mon, 1 Sep 2014 15:23:40 +1200 Subject: [PATCH] Bug 1057212 - Avoid copying all the tiles when doing PushGroupAndCopyBackground. r=Bas --- gfx/2d/DrawTargetTiled.cpp | 46 -------------------------------------- gfx/2d/DrawTargetTiled.h | 43 +++++++++++++++++++++++++++++++++++ gfx/2d/moz.build | 1 + gfx/thebes/gfxContext.cpp | 29 ++++++++++++++++++++---- 4 files changed, 69 insertions(+), 50 deletions(-) diff --git a/gfx/2d/DrawTargetTiled.cpp b/gfx/2d/DrawTargetTiled.cpp index de7f93aada1..75f7b5c2057 100644 --- a/gfx/2d/DrawTargetTiled.cpp +++ b/gfx/2d/DrawTargetTiled.cpp @@ -45,52 +45,6 @@ DrawTargetTiled::Init(const TileSet& aTiles) return true; } -class SnapshotTiled : public SourceSurface -{ -public: - SnapshotTiled(const vector& aTiles, const IntRect& aRect) - : mRect(aRect) - { - for (size_t i = 0; i < aTiles.size(); i++) { - mSnapshots.push_back(aTiles[i].mDrawTarget->Snapshot()); - mOrigins.push_back(aTiles[i].mTileOrigin); - } - } - - virtual SurfaceType GetType() const { return SurfaceType::TILED; } - virtual IntSize GetSize() const { return IntSize(mRect.XMost(), mRect.YMost()); } - virtual SurfaceFormat GetFormat() const { return mSnapshots[0]->GetFormat(); } - - virtual TemporaryRef GetDataSurface() - { - RefPtr surf = Factory::CreateDataSourceSurface(GetSize(), GetFormat()); - if (MOZ2D_WARN_IF(!surf)) { - return nullptr; - } - - DataSourceSurface::MappedSurface mappedSurf; - surf->Map(DataSourceSurface::MapType::WRITE, &mappedSurf); - - { - RefPtr dt = - Factory::CreateDrawTargetForData(BackendType::CAIRO, mappedSurf.mData, - GetSize(), mappedSurf.mStride, GetFormat()); - - for (size_t i = 0; i < mSnapshots.size(); i++) { - RefPtr dataSurf = mSnapshots[i]->GetDataSurface(); - dt->CopySurface(dataSurf, IntRect(IntPoint(0, 0), mSnapshots[i]->GetSize()), mOrigins[i]); - } - } - surf->Unmap(); - - return surf.forget(); - } -private: - vector> mSnapshots; - vector mOrigins; - IntRect mRect; -}; - TemporaryRef DrawTargetTiled::Snapshot() { diff --git a/gfx/2d/DrawTargetTiled.h b/gfx/2d/DrawTargetTiled.h index de948797a73..b29f7c7251a 100644 --- a/gfx/2d/DrawTargetTiled.h +++ b/gfx/2d/DrawTargetTiled.h @@ -149,6 +149,49 @@ private: IntRect mRect; }; +class SnapshotTiled : public SourceSurface +{ +public: + SnapshotTiled(const std::vector& aTiles, const IntRect& aRect) + : mRect(aRect) + { + for (size_t i = 0; i < aTiles.size(); i++) { + mSnapshots.push_back(aTiles[i].mDrawTarget->Snapshot()); + mOrigins.push_back(aTiles[i].mTileOrigin); + } + } + + virtual SurfaceType GetType() const { return SurfaceType::TILED; } + virtual IntSize GetSize() const { return IntSize(mRect.XMost(), mRect.YMost()); } + virtual SurfaceFormat GetFormat() const { return mSnapshots[0]->GetFormat(); } + + virtual TemporaryRef GetDataSurface() + { + RefPtr surf = Factory::CreateDataSourceSurface(GetSize(), GetFormat()); + + DataSourceSurface::MappedSurface mappedSurf; + surf->Map(DataSourceSurface::MapType::WRITE, &mappedSurf); + + { + RefPtr dt = + Factory::CreateDrawTargetForData(BackendType::CAIRO, mappedSurf.mData, + GetSize(), mappedSurf.mStride, GetFormat()); + + for (size_t i = 0; i < mSnapshots.size(); i++) { + RefPtr dataSurf = mSnapshots[i]->GetDataSurface(); + dt->CopySurface(dataSurf, IntRect(IntPoint(0, 0), mSnapshots[i]->GetSize()), mOrigins[i]); + } + } + surf->Unmap(); + + return surf.forget(); + } + + std::vector> mSnapshots; + std::vector mOrigins; + IntRect mRect; +}; + } } diff --git a/gfx/2d/moz.build b/gfx/2d/moz.build index 8802518e37e..31a7228178f 100644 --- a/gfx/2d/moz.build +++ b/gfx/2d/moz.build @@ -21,6 +21,7 @@ EXPORTS.mozilla.gfx += [ 'BorrowedContext.h', 'Coord.h', 'DataSurfaceHelpers.h', + 'DrawTargetTiled.h', 'Filters.h', 'Helpers.h', 'Logging.h', diff --git a/gfx/thebes/gfxContext.cpp b/gfx/thebes/gfxContext.cpp index ecb586d7e61..58daf12dabd 100644 --- a/gfx/thebes/gfxContext.cpp +++ b/gfx/thebes/gfxContext.cpp @@ -24,6 +24,7 @@ #include "GeckoProfiler.h" #include "gfx2DGlue.h" #include "mozilla/gfx/PathHelpers.h" +#include "mozilla/gfx/DrawTargetTiled.h" #include #if CAIRO_HAS_DWRITE_FONT @@ -1118,12 +1119,32 @@ gfxContext::PushGroupAndCopyBackground(gfxContentType content) Point offset = CurrentState().deviceOffset - oldDeviceOffset; Rect surfRect(0, 0, Float(mDT->GetSize().width), Float(mDT->GetSize().height)); - Rect sourceRect = surfRect; - sourceRect.x += offset.x; - sourceRect.y += offset.y; + Rect sourceRect = surfRect + offset; mDT->SetTransform(Matrix()); - mDT->DrawSurface(source, surfRect, sourceRect); + + // XXX: It's really sad that we have to do this (for performance). + // Once DrawTarget gets a PushLayer API we can implement this within + // DrawTargetTiled. + if (source->GetType() == SurfaceType::TILED) { + SnapshotTiled *sourceTiled = static_cast(source.get()); + for (uint32_t i = 0; i < sourceTiled->mSnapshots.size(); i++) { + Rect tileSourceRect = sourceRect.Intersect(Rect(sourceTiled->mOrigins[i].x, + sourceTiled->mOrigins[i].y, + sourceTiled->mSnapshots[i]->GetSize().width, + sourceTiled->mSnapshots[i]->GetSize().height)); + + if (tileSourceRect.IsEmpty()) { + continue; + } + Rect tileDestRect = tileSourceRect - offset; + tileSourceRect -= sourceTiled->mOrigins[i]; + + mDT->DrawSurface(sourceTiled->mSnapshots[i], tileDestRect, tileSourceRect); + } + } else { + mDT->DrawSurface(source, surfRect, sourceRect); + } mDT->SetOpaqueRect(oldDT->GetOpaqueRect()); PushClipsToDT(mDT);