mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-25 03:05:34 +00:00
0b68652b49
This changes CreateClippedDrawTarget so that instead of taking a max size and a transform it just takes a user space rect of the desired bounds. This change allows the caller to not worry about the computing a max size based on the current clip. Instead this responsibility is lowered into the specific backends. The main motivation for this work is to allow blob recoordination to create recordings that don't depend on the current clip. Some additional benefits are that the API is easier to use and as can be seen simplifies the SVG masking code because it doesn't need to track surface offsets manually. It's also an important step towards removing all the uses of gfxContext::GetClipExtents which will let us get rid of the separate clipping stack in gfxContext and help us move off of gfxContext completely. Most backend implementations of CreateClippedDrawTarget are relatively simple. DrawTargetCapture is modified to track the current clip rect so that it can create a new DrawTargetCapture of the appropriate size without needing to worry about lazy resolution. Differential Revision: https://phabricator.services.mozilla.com/D33363 --HG-- extra : moz-landing-system : lando
247 lines
8.9 KiB
C++
247 lines
8.9 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef MOZILLA_GFX_DRAWTARGETTILED_H_
|
|
#define MOZILLA_GFX_DRAWTARGETTILED_H_
|
|
|
|
#include "2D.h"
|
|
|
|
#include "mozilla/Vector.h"
|
|
|
|
#include "Filters.h"
|
|
#include "Logging.h"
|
|
|
|
#include <vector>
|
|
|
|
namespace mozilla {
|
|
namespace gfx {
|
|
|
|
struct TileInternal : public Tile {
|
|
TileInternal() : mClippedOut(false) {}
|
|
|
|
explicit TileInternal(const Tile& aOther)
|
|
: Tile(aOther), mClippedOut(false) {}
|
|
|
|
bool mClippedOut;
|
|
};
|
|
|
|
class DrawTargetTiled : public DrawTarget {
|
|
public:
|
|
DrawTargetTiled();
|
|
|
|
bool Init(const TileSet& mTiles);
|
|
|
|
bool IsTiledDrawTarget() const override { return true; }
|
|
|
|
bool IsCaptureDT() const override {
|
|
return mTiles[0].mDrawTarget->IsCaptureDT();
|
|
}
|
|
DrawTargetType GetType() const override {
|
|
return mTiles[0].mDrawTarget->GetType();
|
|
}
|
|
BackendType GetBackendType() const override {
|
|
return mTiles[0].mDrawTarget->GetBackendType();
|
|
}
|
|
already_AddRefed<SourceSurface> Snapshot() override;
|
|
void DetachAllSnapshots() override;
|
|
IntSize GetSize() const override {
|
|
MOZ_ASSERT(mRect.Width() > 0 && mRect.Height() > 0);
|
|
return IntSize(mRect.XMost(), mRect.YMost());
|
|
}
|
|
IntRect GetRect() const override { return mRect; }
|
|
|
|
void Flush() override;
|
|
void DrawSurface(SourceSurface* aSurface, const Rect& aDest,
|
|
const Rect& aSource, const DrawSurfaceOptions& aSurfOptions,
|
|
const DrawOptions& aOptions) override;
|
|
void DrawFilter(FilterNode* aNode, const Rect& aSourceRect,
|
|
const Point& aDestPoint,
|
|
const DrawOptions& aOptions = DrawOptions()) override;
|
|
void DrawSurfaceWithShadow(
|
|
SourceSurface* aSurface, const Point& aDest, const Color& aColor,
|
|
const Point& aOffset, Float aSigma,
|
|
CompositionOp aOperator) override { /* Not implemented */
|
|
MOZ_CRASH("GFX: DrawSurfaceWithShadow");
|
|
}
|
|
|
|
void ClearRect(const Rect& aRect) override;
|
|
void MaskSurface(const Pattern& aSource, SourceSurface* aMask, Point aOffset,
|
|
const DrawOptions& aOptions = DrawOptions()) override;
|
|
|
|
void CopySurface(SourceSurface* aSurface, const IntRect& aSourceRect,
|
|
const IntPoint& aDestination) override;
|
|
|
|
void FillRect(const Rect& aRect, const Pattern& aPattern,
|
|
const DrawOptions& aOptions = DrawOptions()) override;
|
|
void StrokeRect(const Rect& aRect, const Pattern& aPattern,
|
|
const StrokeOptions& aStrokeOptions = StrokeOptions(),
|
|
const DrawOptions& aOptions = DrawOptions()) override;
|
|
void StrokeLine(const Point& aStart, const Point& aEnd,
|
|
const Pattern& aPattern,
|
|
const StrokeOptions& aStrokeOptions = StrokeOptions(),
|
|
const DrawOptions& aOptions = DrawOptions()) override;
|
|
void Stroke(const Path* aPath, const Pattern& aPattern,
|
|
const StrokeOptions& aStrokeOptions = StrokeOptions(),
|
|
const DrawOptions& aOptions = DrawOptions()) override;
|
|
void Fill(const Path* aPath, const Pattern& aPattern,
|
|
const DrawOptions& aOptions = DrawOptions()) override;
|
|
void FillGlyphs(ScaledFont* aFont, const GlyphBuffer& aBuffer,
|
|
const Pattern& aPattern,
|
|
const DrawOptions& aOptions = DrawOptions()) override;
|
|
void Mask(const Pattern& aSource, const Pattern& aMask,
|
|
const DrawOptions& aOptions = DrawOptions()) override;
|
|
void PushClip(const Path* aPath) override;
|
|
void PushClipRect(const Rect& aRect) override;
|
|
void PopClip() override;
|
|
void PushLayer(bool aOpaque, Float aOpacity, SourceSurface* aMask,
|
|
const Matrix& aMaskTransform,
|
|
const IntRect& aBounds = IntRect(),
|
|
bool aCopyBackground = false) override;
|
|
void PushLayerWithBlend(bool aOpaque, Float aOpacity, SourceSurface* aMask,
|
|
const Matrix& aMaskTransform,
|
|
const IntRect& aBounds = IntRect(),
|
|
bool aCopyBackground = false,
|
|
CompositionOp = CompositionOp::OP_OVER) override;
|
|
void PopLayer() override;
|
|
|
|
void PadEdges(const IntRegion& aRegion) override;
|
|
|
|
void SetTransform(const Matrix& aTransform) override;
|
|
|
|
void SetPermitSubpixelAA(bool aPermitSubpixelAA) override;
|
|
|
|
already_AddRefed<SourceSurface> CreateSourceSurfaceFromData(
|
|
unsigned char* aData, const IntSize& aSize, int32_t aStride,
|
|
SurfaceFormat aFormat) const override {
|
|
return mTiles[0].mDrawTarget->CreateSourceSurfaceFromData(aData, aSize,
|
|
aStride, aFormat);
|
|
}
|
|
already_AddRefed<SourceSurface> OptimizeSourceSurface(
|
|
SourceSurface* aSurface) const override {
|
|
return mTiles[0].mDrawTarget->OptimizeSourceSurface(aSurface);
|
|
}
|
|
|
|
already_AddRefed<SourceSurface> CreateSourceSurfaceFromNativeSurface(
|
|
const NativeSurface& aSurface) const override {
|
|
return mTiles[0].mDrawTarget->CreateSourceSurfaceFromNativeSurface(
|
|
aSurface);
|
|
}
|
|
|
|
already_AddRefed<DrawTarget> CreateSimilarDrawTarget(
|
|
const IntSize& aSize, SurfaceFormat aFormat) const override {
|
|
return mTiles[0].mDrawTarget->CreateSimilarDrawTarget(aSize, aFormat);
|
|
}
|
|
|
|
bool CanCreateSimilarDrawTarget(const IntSize& aSize,
|
|
SurfaceFormat aFormat) const override {
|
|
return mTiles[0].mDrawTarget->CanCreateSimilarDrawTarget(aSize, aFormat);
|
|
}
|
|
|
|
RefPtr<DrawTarget> CreateClippedDrawTarget(const Rect& aBounds,
|
|
SurfaceFormat aFormat) override;
|
|
|
|
already_AddRefed<PathBuilder> CreatePathBuilder(
|
|
FillRule aFillRule = FillRule::FILL_WINDING) const override {
|
|
return mTiles[0].mDrawTarget->CreatePathBuilder(aFillRule);
|
|
}
|
|
|
|
already_AddRefed<GradientStops> CreateGradientStops(
|
|
GradientStop* aStops, uint32_t aNumStops,
|
|
ExtendMode aExtendMode = ExtendMode::CLAMP) const override {
|
|
return mTiles[0].mDrawTarget->CreateGradientStops(aStops, aNumStops,
|
|
aExtendMode);
|
|
}
|
|
already_AddRefed<FilterNode> CreateFilter(FilterType aType) override {
|
|
return mTiles[0].mDrawTarget->CreateFilter(aType);
|
|
}
|
|
|
|
private:
|
|
std::vector<TileInternal> mTiles;
|
|
|
|
// mClippedOutTilesStack[clipIndex][tileIndex] is true if the tile at
|
|
// tileIndex has become completely clipped out at the clip stack depth
|
|
// clipIndex.
|
|
Vector<std::vector<bool>, 8> mClippedOutTilesStack;
|
|
|
|
IntRect mRect;
|
|
|
|
struct PushedLayer {
|
|
explicit PushedLayer(bool aOldPermitSubpixelAA)
|
|
: mOldPermitSubpixelAA(aOldPermitSubpixelAA) {}
|
|
bool mOldPermitSubpixelAA;
|
|
};
|
|
std::vector<PushedLayer> mPushedLayers;
|
|
};
|
|
|
|
class SnapshotTiled : public SourceSurface {
|
|
public:
|
|
SnapshotTiled(const std::vector<TileInternal>& 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);
|
|
}
|
|
}
|
|
|
|
SurfaceType GetType() const override { return SurfaceType::TILED; }
|
|
IntSize GetSize() const override {
|
|
MOZ_ASSERT(mRect.Width() > 0 && mRect.Height() > 0);
|
|
return IntSize(mRect.XMost(), mRect.YMost());
|
|
}
|
|
IntRect GetRect() const override { return mRect; }
|
|
SurfaceFormat GetFormat() const override {
|
|
return mSnapshots[0]->GetFormat();
|
|
}
|
|
|
|
already_AddRefed<DataSourceSurface> GetDataSurface() override {
|
|
RefPtr<DataSourceSurface> surf =
|
|
Factory::CreateDataSourceSurface(mRect.Size(), GetFormat());
|
|
if (!surf) {
|
|
gfxCriticalError()
|
|
<< "DrawTargetTiled::GetDataSurface failed to allocate surface";
|
|
return nullptr;
|
|
}
|
|
|
|
DataSourceSurface::MappedSurface mappedSurf;
|
|
if (!surf->Map(DataSourceSurface::MapType::WRITE, &mappedSurf)) {
|
|
gfxCriticalError()
|
|
<< "DrawTargetTiled::GetDataSurface failed to map surface";
|
|
return nullptr;
|
|
}
|
|
|
|
{
|
|
RefPtr<DrawTarget> dt = Factory::CreateDrawTargetForData(
|
|
BackendType::CAIRO, mappedSurf.mData, mRect.Size(),
|
|
mappedSurf.mStride, GetFormat());
|
|
|
|
if (!dt) {
|
|
gfxWarning() << "DrawTargetTiled::GetDataSurface failed in "
|
|
"CreateDrawTargetForData";
|
|
surf->Unmap();
|
|
return nullptr;
|
|
}
|
|
for (size_t i = 0; i < mSnapshots.size(); i++) {
|
|
RefPtr<DataSourceSurface> dataSurf = mSnapshots[i]->GetDataSurface();
|
|
dt->CopySurface(dataSurf,
|
|
IntRect(IntPoint(0, 0), mSnapshots[i]->GetSize()),
|
|
mOrigins[i] - mRect.TopLeft());
|
|
}
|
|
}
|
|
surf->Unmap();
|
|
|
|
return surf.forget();
|
|
}
|
|
|
|
std::vector<RefPtr<SourceSurface>> mSnapshots;
|
|
std::vector<IntPoint> mOrigins;
|
|
IntRect mRect;
|
|
};
|
|
|
|
} // namespace gfx
|
|
} // namespace mozilla
|
|
|
|
#endif
|