From da852fb01695c4e9d45607e3119ec8c0db73e53c Mon Sep 17 00:00:00 2001 From: Jonathan Watt Date: Fri, 5 Dec 2014 03:00:24 -0800 Subject: [PATCH] Bug 1083079 - Prevent the size of TiledDrawTarget from being zero due to its tiles having negative offsets. r=mattwoodrow --- gfx/2d/DrawTargetTiled.h | 10 ++++++++-- gfx/layers/client/TiledContentClient.cpp | 10 +++++++++- gfx/layers/client/TiledContentClient.h | 13 +++++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/gfx/2d/DrawTargetTiled.h b/gfx/2d/DrawTargetTiled.h index 7190c986c595..520428861389 100644 --- a/gfx/2d/DrawTargetTiled.h +++ b/gfx/2d/DrawTargetTiled.h @@ -40,7 +40,10 @@ public: virtual DrawTargetType GetType() const MOZ_OVERRIDE { return mTiles[0].mDrawTarget->GetType(); } virtual BackendType GetBackendType() const { return mTiles[0].mDrawTarget->GetBackendType(); } virtual TemporaryRef Snapshot(); - virtual IntSize GetSize() { return IntSize(mRect.XMost(), mRect.YMost()); } + virtual IntSize GetSize() { + MOZ_ASSERT(mRect.width > 0 && mRect.height > 0); + return IntSize(mRect.XMost(), mRect.YMost()); + } virtual void Flush(); virtual void DrawSurface(SourceSurface *aSurface, @@ -162,7 +165,10 @@ public: } virtual SurfaceType GetType() const { return SurfaceType::TILED; } - virtual IntSize GetSize() const { return IntSize(mRect.XMost(), mRect.YMost()); } + virtual IntSize GetSize() const { + MOZ_ASSERT(mRect.width > 0 && mRect.height > 0); + return IntSize(mRect.XMost(), mRect.YMost()); + } virtual SurfaceFormat GetFormat() const { return mSnapshots[0]->GetFormat(); } virtual TemporaryRef GetDataSurface() diff --git a/gfx/layers/client/TiledContentClient.cpp b/gfx/layers/client/TiledContentClient.cpp index 9e65dff8ac11..16c6fb6f0748 100644 --- a/gfx/layers/client/TiledContentClient.cpp +++ b/gfx/layers/client/TiledContentClient.cpp @@ -1056,6 +1056,9 @@ ClientTiledLayerBuffer::PostValidate(const nsIntRegion& aPaintRegion) { if (gfxPrefs::TiledDrawTargetEnabled() && mMoz2DTiles.size() > 0) { gfx::TileSet tileset; + for (size_t i = 0; i < mMoz2DTiles.size(); ++i) { + mMoz2DTiles[i].mTileOrigin -= mTilingOrigin; + } tileset.mTiles = &mMoz2DTiles[0]; tileset.mTileCount = mMoz2DTiles.size(); RefPtr drawTarget = gfx::Factory::CreateTiledDrawTarget(tileset); @@ -1063,10 +1066,13 @@ ClientTiledLayerBuffer::PostValidate(const nsIntRegion& aPaintRegion) RefPtr ctx = new gfxContext(drawTarget); ctx->SetMatrix( - ctx->CurrentMatrix().Scale(mResolution, mResolution)); + ctx->CurrentMatrix().Scale(mResolution, mResolution).Translate(ThebesPoint(-mTilingOrigin))); mCallback(mPaintedLayer, ctx, aPaintRegion, DrawRegionClip::DRAW, nsIntRegion(), mCallbackData); mMoz2DTiles.clear(); + // Reset: + mTilingOrigin = IntPoint(std::numeric_limits::max(), + std::numeric_limits::max()); } } @@ -1188,6 +1194,8 @@ ClientTiledLayerBuffer::ValidateTile(TileClient aTile, } mMoz2DTiles.push_back(moz2DTile); + mTilingOrigin.x = std::min(mTilingOrigin.x, moz2DTile.mTileOrigin.x); + mTilingOrigin.y = std::min(mTilingOrigin.y, moz2DTile.mTileOrigin.y); nsIntRegionRectIterator it(aDirtyRegion); for (const nsIntRect* dirtyRect = it.Next(); dirtyRect != nullptr; dirtyRect = it.Next()) { diff --git a/gfx/layers/client/TiledContentClient.h b/gfx/layers/client/TiledContentClient.h index 46d796c3a5e8..6fb767f3c284 100644 --- a/gfx/layers/client/TiledContentClient.h +++ b/gfx/layers/client/TiledContentClient.h @@ -9,6 +9,7 @@ #include // for size_t #include // for uint16_t #include // for swap +#include #include "Layers.h" // for LayerManager, etc #include "TiledLayerBuffer.h" // for TiledLayerBuffer #include "Units.h" // for CSSPoint @@ -399,6 +400,8 @@ public: , mLastPaintContentType(gfxContentType::COLOR) , mLastPaintSurfaceMode(SurfaceMode::SURFACE_OPAQUE) , mSharedFrameMetricsHelper(nullptr) + , mTilingOrigin(std::numeric_limits::max(), + std::numeric_limits::max()) {} void PaintThebes(const nsIntRegion& aNewValidRegion, @@ -475,6 +478,16 @@ private: SharedFrameMetricsHelper* mSharedFrameMetricsHelper; // When using Moz2D's CreateTiledDrawTarget we maintain a list of gfx::Tiles std::vector mMoz2DTiles; + /** + * While we're adding tiles, this is used to keep track of the position of + * the top-left of the top-left-most tile. When we come to wrap the tiles in + * TiledDrawTarget we subtract the value of this member from each tile's + * offset so that all the tiles have a positive offset, then add a + * translation to the TiledDrawTarget to compensate. This is important so + * that the mRect of the TiledDrawTarget is always at a positive x/y + * position, otherwise its GetSize() methods will be broken. + */ + gfx::IntPoint mTilingOrigin; /** * Calculates the region to update in a single progressive update transaction. * This employs some heuristics to update the most 'sensible' region to