--- a/gfx/layers/basic/BasicCompositor.cpp
+++ b/gfx/layers/basic/BasicCompositor.cpp
@@ -351,25 +351,110 @@ BasicCompositor::CreateDataTextureSource
}
bool
BasicCompositor::SupportsEffect(EffectTypes aEffect)
{
return aEffect != EffectTypes::YCBCR && aEffect != EffectTypes::COMPONENT_ALPHA;
}
+bool
+BasicCompositor::SupportsLayerGeometry() const
+{
+ return gfxPrefs::BasicLayerGeometry();
+}
+
+static RefPtr<gfx::Path>
+BuildPathFromPolygon(const RefPtr<DrawTarget>& aDT,
+ const gfx::Polygon& aPolygon)
+{
+ RefPtr<PathBuilder> pathBuilder = aDT->CreatePathBuilder();
+ const nsTArray<Point4D>& points = aPolygon.GetPoints();
+
+ pathBuilder->MoveTo(points[0].As2DPoint());
+
+ for (size_t i = 1; i < points.Length(); ++i) {
+ pathBuilder->LineTo(points[i].As2DPoint());
+ }
+
+ pathBuilder->Close();
+ return pathBuilder->Finish();
+}
+
static void
-DrawSurfaceWithTextureCoords(DrawTarget *aDest,
+DrawSurface(gfx::DrawTarget* aDest,
+ const gfx::Rect& aDestRect,
+ const gfx::Rect& /* aClipRect */,
+ const gfx::Color& aColor,
+ const gfx::DrawOptions& aOptions,
+ gfx::SourceSurface* aMask,
+ const gfx::Matrix* aMaskTransform)
+{
+ FillRectWithMask(aDest, aDestRect, aColor,
+ aOptions, aMask, aMaskTransform);
+}
+
+static void
+DrawSurface(gfx::DrawTarget* aDest,
+ const gfx::Polygon& aPolygon,
+ const gfx::Rect& aClipRect,
+ const gfx::Color& aColor,
+ const gfx::DrawOptions& aOptions,
+ gfx::SourceSurface* aMask,
+ const gfx::Matrix* aMaskTransform)
+{
+ RefPtr<Path> path = BuildPathFromPolygon(aDest, aPolygon);
+ FillPathWithMask(aDest, path, aClipRect, aColor,
+ aOptions, aMask, aMaskTransform);
+}
+
+static void
+DrawTextureSurface(gfx::DrawTarget* aDest,
+ const gfx::Rect& aDestRect,
+ const gfx::Rect& /* aClipRect */,
+ gfx::SourceSurface* aSource,
+ gfx::SamplingFilter aSamplingFilter,
+ const gfx::DrawOptions& aOptions,
+ ExtendMode aExtendMode,
+ gfx::SourceSurface* aMask,
+ const gfx::Matrix* aMaskTransform,
+ const Matrix* aSurfaceTransform)
+{
+ FillRectWithMask(aDest, aDestRect, aSource, aSamplingFilter, aOptions,
+ aExtendMode, aMask, aMaskTransform, aSurfaceTransform);
+}
+
+static void
+DrawTextureSurface(gfx::DrawTarget* aDest,
+ const gfx::Polygon& aPolygon,
+ const gfx::Rect& aClipRect,
+ gfx::SourceSurface* aSource,
+ gfx::SamplingFilter aSamplingFilter,
+ const gfx::DrawOptions& aOptions,
+ ExtendMode aExtendMode,
+ gfx::SourceSurface* aMask,
+ const gfx::Matrix* aMaskTransform,
+ const Matrix* aSurfaceTransform)
+{
+ RefPtr<Path> path = BuildPathFromPolygon(aDest, aPolygon);
+ FillPathWithMask(aDest, path, aClipRect, aSource, aSamplingFilter, aOptions,
+ aExtendMode, aMask, aMaskTransform, aSurfaceTransform);
+}
+
+template<typename Geometry>
+static void
+DrawSurfaceWithTextureCoords(gfx::DrawTarget* aDest,
+ const Geometry& aGeometry,
const gfx::Rect& aDestRect,
- SourceSurface *aSource,
+ gfx::SourceSurface* aSource,
const gfx::Rect& aTextureCoords,
gfx::SamplingFilter aSamplingFilter,
- const DrawOptions& aOptions,
- SourceSurface *aMask,
- const Matrix* aMaskTransform)
+ const gfx::DrawOptions& aOptions,
+ gfx::SourceSurface* aMask,
+ const gfx::Matrix* aMaskTransform)
{
if (!aSource) {
gfxWarning() << "DrawSurfaceWithTextureCoords problem " << gfx::hexa(aSource) << " and " << gfx::hexa(aMask);
return;
}
// Convert aTextureCoords into aSource's coordinate space
gfxRect sourceRect(aTextureCoords.x * aSource->GetSize().width,
@@ -387,18 +472,18 @@ DrawSurfaceWithTextureCoords(DrawTarget
gfx::IntPoint::Truncate(aDestRect.x, aDestRect.y),
gfx::IntPoint::Truncate(aDestRect.XMost(), aDestRect.y),
gfx::IntPoint::Truncate(aDestRect.XMost(), aDestRect.YMost()));
// Only use REPEAT if aTextureCoords is outside (0, 0, 1, 1).
gfx::Rect unitRect(0, 0, 1, 1);
ExtendMode mode = unitRect.Contains(aTextureCoords) ? ExtendMode::CLAMP : ExtendMode::REPEAT;
- FillRectWithMask(aDest, aDestRect, aSource, aSamplingFilter, aOptions,
- mode, aMask, aMaskTransform, &matrix);
+ DrawTextureSurface(aDest, aGeometry, aDestRect, aSource, aSamplingFilter,
+ aOptions, mode, aMask, aMaskTransform, &matrix);
}
static void
SetupMask(const EffectChain& aEffectChain,
DrawTarget* aDest,
const IntPoint& aOffset,
RefPtr<SourceSurface>& aMaskSurface,
Matrix& aMaskTransform)
@@ -548,16 +633,45 @@ AttemptVideoConvertAndScale(TextureSourc
void
BasicCompositor::DrawQuad(const gfx::Rect& aRect,
const gfx::IntRect& aClipRect,
const EffectChain &aEffectChain,
gfx::Float aOpacity,
const gfx::Matrix4x4& aTransform,
const gfx::Rect& aVisibleRect)
{
+ DrawGeometry(aRect, aRect, aClipRect, aEffectChain,
+ aOpacity, aTransform, aVisibleRect, true);
+}
+
+void
+BasicCompositor::DrawPolygon(const gfx::Polygon& aPolygon,
+ const gfx::Rect& aRect,
+ const gfx::IntRect& aClipRect,
+ const EffectChain& aEffectChain,
+ gfx::Float aOpacity,
+ const gfx::Matrix4x4& aTransform,
+ const gfx::Rect& aVisibleRect)
+{
+ DrawGeometry(aPolygon, aRect, aClipRect, aEffectChain,
+ aOpacity, aTransform, aVisibleRect, false);
+}
+
+
+template<typename Geometry>
+void
+BasicCompositor::DrawGeometry(const Geometry& aGeometry,
+ const gfx::Rect& aRect,
+ const gfx::IntRect& aClipRect,
+ const EffectChain& aEffectChain,
+ gfx::Float aOpacity,
+ const gfx::Matrix4x4& aTransform,
+ const gfx::Rect& aVisibleRect,
+ const bool aEnableAA)
+{
RefPtr<DrawTarget> buffer = mRenderTarget->mDrawTarget;
// For 2D drawing, |dest| and |buffer| are the same surface. For 3D drawing,
// |dest| is a temporary surface.
RefPtr<DrawTarget> dest = buffer;
AutoRestoreTransform autoRestoreTransform(dest);
@@ -608,28 +722,33 @@ BasicCompositor::DrawQuad(const gfx::Rec
SetupMask(aEffectChain, dest, offset, sourceMask, maskTransform);
}
CompositionOp blendMode = CompositionOp::OP_OVER;
if (Effect* effect = aEffectChain.mSecondaryEffects[EffectTypes::BLEND_MODE].get()) {
blendMode = static_cast<EffectBlendMode*>(effect)->mBlendMode;
}
+ const AntialiasMode aaMode =
+ aEnableAA ? AntialiasMode::DEFAULT : AntialiasMode::NONE;
+
+ DrawOptions drawOptions(aOpacity, blendMode, aaMode);
+
switch (aEffectChain.mPrimaryEffect->mType) {
case EffectTypes::SOLID_COLOR: {
EffectSolidColor* effectSolidColor =
static_cast<EffectSolidColor*>(aEffectChain.mPrimaryEffect.get());
bool unboundedOp = !IsOperatorBoundByMask(blendMode);
if (unboundedOp) {
dest->PushClipRect(aRect);
}
- FillRectWithMask(dest, aRect, effectSolidColor->mColor,
- DrawOptions(aOpacity, blendMode), sourceMask, &maskTransform);
+ DrawSurface(dest, aGeometry, aRect, effectSolidColor->mColor,
+ drawOptions, sourceMask, &maskTransform);
if (unboundedOp) {
dest->PopClip();
}
break;
}
case EffectTypes::RGB: {
TexturedEffect* texturedEffect =
@@ -649,37 +768,37 @@ BasicCompositor::DrawQuad(const gfx::Rec
gfxWarning() << "Failed to get YCbCr to rgb surface.";
} else if (source->mFromYCBCR &&
AttemptVideoScale(source, sourceMask, aOpacity, blendMode,
texturedEffect,
newTransform, aRect, transformedClipRect,
dest, buffer)) {
// we succeeded in scaling
} else {
- DrawSurfaceWithTextureCoords(dest, aRect,
+ DrawSurfaceWithTextureCoords(dest, aGeometry, aRect,
source->GetSurface(dest),
texturedEffect->mTextureCoords,
texturedEffect->mSamplingFilter,
- DrawOptions(aOpacity, blendMode),
+ drawOptions,
sourceMask, &maskTransform);
}
} else if (source) {
SourceSurface* srcSurf = source->GetSurface(dest);
if (srcSurf) {
RefPtr<DataSourceSurface> srcData = srcSurf->GetDataSurface();
// Yes, we re-create the premultiplied data every time.
// This might be better with a cache, eventually.
RefPtr<DataSourceSurface> premultData = gfxUtils::CreatePremultipliedDataSurface(srcData);
- DrawSurfaceWithTextureCoords(dest, aRect,
+ DrawSurfaceWithTextureCoords(dest, aGeometry, aRect,
premultData,
texturedEffect->mTextureCoords,
texturedEffect->mSamplingFilter,
- DrawOptions(aOpacity, blendMode),
+ drawOptions,
sourceMask, &maskTransform);
}
} else {
gfxDevCrash(LogReason::IncompatibleBasicTexturedEffect) << "Bad for basic with " << texturedEffect->mTexture->Name() << " and " << gfx::hexa(sourceMask);
}
break;
}
@@ -689,21 +808,21 @@ BasicCompositor::DrawQuad(const gfx::Rec
}
case EffectTypes::RENDER_TARGET: {
EffectRenderTarget* effectRenderTarget =
static_cast<EffectRenderTarget*>(aEffectChain.mPrimaryEffect.get());
RefPtr<BasicCompositingRenderTarget> surface
= static_cast<BasicCompositingRenderTarget*>(effectRenderTarget->mRenderTarget.get());
RefPtr<SourceSurface> sourceSurf = surface->mDrawTarget->Snapshot();
- DrawSurfaceWithTextureCoords(dest, aRect,
+ DrawSurfaceWithTextureCoords(dest, aGeometry, aRect,
sourceSurf,
effectRenderTarget->mTextureCoords,
effectRenderTarget->mSamplingFilter,
- DrawOptions(aOpacity, blendMode),
+ drawOptions,
sourceMask, &maskTransform);
break;
}
case EffectTypes::COMPONENT_ALPHA: {
MOZ_CRASH("Can't (easily) support component alpha with BasicCompositor!");
break;
}
default: {
--- a/gfx/layers/basic/BasicCompositor.h
+++ b/gfx/layers/basic/BasicCompositor.h
@@ -4,16 +4,18 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MOZILLA_GFX_BASICCOMPOSITOR_H
#define MOZILLA_GFX_BASICCOMPOSITOR_H
#include "mozilla/layers/Compositor.h"
#include "mozilla/layers/TextureHost.h"
#include "mozilla/gfx/2D.h"
+#include "mozilla/gfx/Triangle.h"
+#include "mozilla/gfx/Polygon.h"
namespace mozilla {
namespace layers {
class BasicCompositingRenderTarget : public CompositingRenderTarget
{
public:
BasicCompositingRenderTarget(gfx::DrawTarget* aDrawTarget, const gfx::IntRect& aRect)
@@ -75,16 +77,18 @@ public:
virtual already_AddRefed<DataTextureSource>
CreateDataTextureSourceAround(gfx::DataSourceSurface* aSurface) override;
virtual already_AddRefed<DataTextureSource>
CreateDataTextureSourceAroundYCbCr(TextureHost* aTexture) override;
virtual bool SupportsEffect(EffectTypes aEffect) override;
+ bool SupportsLayerGeometry() const override;
+
virtual void SetRenderTarget(CompositingRenderTarget *aSource) override
{
mRenderTarget = static_cast<BasicCompositingRenderTarget*>(aSource);
mRenderTarget->BindRenderTarget();
}
virtual CompositingRenderTarget* GetCurrentRenderTarget() const override
{
return mRenderTarget;
@@ -106,17 +110,17 @@ public:
gfx::IntRect *aClipRectOut = nullptr,
gfx::IntRect *aRenderBoundsOut = nullptr) override;
virtual void EndFrame() override;
virtual bool SupportsPartialTextureUpdate() override { return true; }
virtual bool CanUseCanvasLayerForSize(const gfx::IntSize &aSize) override { return true; }
virtual int32_t GetMaxTextureSize() const override;
virtual void SetDestinationSurfaceSize(const gfx::IntSize& aSize) override { }
-
+
virtual void SetScreenRenderOffset(const ScreenPoint& aOffset) override {
}
virtual void MakeCurrent(MakeCurrentFlags aFlags = 0) override { }
#ifdef MOZ_DUMP_PAINTING
virtual const char* Name() const override { return "Basic"; }
#endif // MOZ_DUMP_PAINTING
@@ -131,16 +135,34 @@ public:
{
return mIsPendingEndRemoteDrawing;
}
virtual void FinishPendingComposite() override;
private:
+ template<typename Geometry>
+ void DrawGeometry(const Geometry& aGeometry,
+ const gfx::Rect& aRect,
+ const gfx::IntRect& aClipRect,
+ const EffectChain& aEffectChain,
+ gfx::Float aOpacity,
+ const gfx::Matrix4x4& aTransform,
+ const gfx::Rect& aVisibleRect,
+ const bool aEnableAA);
+
+ virtual void DrawPolygon(const gfx::Polygon& aPolygon,
+ const gfx::Rect& aRect,
+ const gfx::IntRect& aClipRect,
+ const EffectChain& aEffectChain,
+ gfx::Float aOpacity,
+ const gfx::Matrix4x4& aTransform,
+ const gfx::Rect& aVisibleRect) override;
+
void TryToEndRemoteDrawing(bool aForceToEnd = false);
bool NeedsToDeferEndRemoteDrawing();
// The final destination surface
RefPtr<gfx::DrawTarget> mDrawTarget;
// The current render target for drawing
RefPtr<BasicCompositingRenderTarget> mRenderTarget;
--- a/gfx/layers/basic/BasicLayersImpl.cpp
+++ b/gfx/layers/basic/BasicLayersImpl.cpp
@@ -201,16 +201,78 @@ FillRectWithMask(DrawTarget* aDT,
mask.GetSurface(), &maskTransform);
return;
}
FillRectWithMask(aDT, aRect, aSurface, aSamplingFilter, aOptions,
ExtendMode::CLAMP);
}
+void
+FillPathWithMask(DrawTarget* aDT,
+ const Path* aPath,
+ const Rect& aClipRect,
+ const Color& aColor,
+ const DrawOptions& aOptions,
+ SourceSurface* aMaskSource,
+ const Matrix* aMaskTransform)
+{
+ if (aMaskSource && aMaskTransform) {
+ aDT->PushClipRect(aClipRect);
+ Matrix oldTransform = aDT->GetTransform();
+
+ aDT->SetTransform(*aMaskTransform);
+ aDT->MaskSurface(ColorPattern(aColor), aMaskSource, Point(), aOptions);
+ aDT->SetTransform(oldTransform);
+ aDT->PopClip();
+ return;
+ }
+
+ aDT->Fill(aPath, ColorPattern(aColor), aOptions);
+}
+
+void
+FillPathWithMask(DrawTarget* aDT,
+ const Path* aPath,
+ const Rect& aClipRect,
+ SourceSurface* aSurface,
+ SamplingFilter aSamplingFilter,
+ const DrawOptions& aOptions,
+ ExtendMode aExtendMode,
+ SourceSurface* aMaskSource,
+ const Matrix* aMaskTransform,
+ const Matrix* aSurfaceTransform)
+{
+ if (aMaskSource && aMaskTransform) {
+ aDT->PushClipRect(aClipRect);
+ Matrix oldTransform = aDT->GetTransform();
+
+ Matrix inverseMask = *aMaskTransform;
+ inverseMask.Invert();
+
+ Matrix transform = oldTransform * inverseMask;
+ if (aSurfaceTransform) {
+ transform = (*aSurfaceTransform) * transform;
+ }
+
+ SurfacePattern source(aSurface, aExtendMode, transform, aSamplingFilter);
+
+ aDT->SetTransform(*aMaskTransform);
+ aDT->MaskSurface(source, aMaskSource, Point(0, 0), aOptions);
+ aDT->SetTransform(oldTransform);
+ aDT->PopClip();
+ return;
+ }
+
+ aDT->Fill(aPath,
+ SurfacePattern(aSurface, aExtendMode,
+ aSurfaceTransform ? (*aSurfaceTransform) : Matrix(),
+ aSamplingFilter), aOptions);
+}
+
BasicImplData*
ToData(Layer* aLayer)
{
return static_cast<BasicImplData*>(aLayer->ImplData());
}
gfx::CompositionOp
GetEffectiveOperator(Layer* aLayer)
--- a/gfx/layers/basic/BasicLayersImpl.h
+++ b/gfx/layers/basic/BasicLayersImpl.h
@@ -122,16 +122,36 @@ FillRectWithMask(gfx::DrawTarget* aDT,
void
FillRectWithMask(gfx::DrawTarget* aDT,
const gfx::Point& aDeviceOffset,
const gfx::Rect& aRect,
const gfx::Color& aColor,
const gfx::DrawOptions& aOptions,
Layer* aMaskLayer);
+void
+FillPathWithMask(gfx::DrawTarget* aDT,
+ const gfx::Path* aPath,
+ const gfx::Rect& aClipRect,
+ const gfx::Color& aColor,
+ const gfx::DrawOptions& aOptions,
+ gfx::SourceSurface* aMaskSource = nullptr,
+ const gfx::Matrix* aMaskTransform = nullptr);
+void
+FillPathWithMask(gfx::DrawTarget* aDT,
+ const gfx::Path* aPath,
+ const gfx::Rect& aClipRect,
+ gfx::SourceSurface* aSurface,
+ gfx::SamplingFilter aSamplingFilter,
+ const gfx::DrawOptions& aOptions,
+ gfx::ExtendMode aExtendMode,
+ gfx::SourceSurface* aMaskSource,
+ const gfx::Matrix* aMaskTransform,
+ const gfx::Matrix* aSurfaceTransform);
+
BasicImplData*
ToData(Layer* aLayer);
/**
* Returns the operator to be used when blending and compositing this layer.
* Currently there is no way to specify both a blending and a compositing
* operator other than normal and source over respectively.
*
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -522,16 +522,17 @@ private:
DECL_GFX_PREF(Once, "layers.tiles.edge-padding", TileEdgePaddingEnabled, bool, true);
DECL_GFX_PREF(Live, "layers.tiles.fade-in.enabled", LayerTileFadeInEnabled, bool, false);
DECL_GFX_PREF(Live, "layers.tiles.fade-in.duration-ms", LayerTileFadeInDuration, uint32_t, 250);
DECL_GFX_PREF(Live, "layers.transaction.warning-ms", LayerTransactionWarning, uint32_t, 200);
DECL_GFX_PREF(Once, "layers.uniformity-info", UniformityInfo, bool, false);
DECL_GFX_PREF(Once, "layers.use-image-offscreen-surfaces", UseImageOffscreenSurfaces, bool, true);
DECL_GFX_PREF(Live, "layers.draw-mask-debug", DrawMaskLayer, bool, false);
DECL_GFX_PREF(Live, "layers.geometry.opengl.enabled", OGLLayerGeometry, bool, false);
+ DECL_GFX_PREF(Live, "layers.geometry.basic.enabled", BasicLayerGeometry, bool, false);
DECL_GFX_PREF(Live, "layout.animation.prerender.partial", PartiallyPrerenderAnimatedContent, bool, false);
DECL_GFX_PREF(Live, "layout.animation.prerender.viewport-ratio-limit-x", AnimationPrerenderViewportRatioLimitX, float, 1.125f);
DECL_GFX_PREF(Live, "layout.animation.prerender.viewport-ratio-limit-y", AnimationPrerenderViewportRatioLimitY, float, 1.125f);
DECL_GFX_PREF(Live, "layout.animation.prerender.absolute-limit-x", AnimationPrerenderAbsoluteLimitX, uint32_t, 4096);
DECL_GFX_PREF(Live, "layout.animation.prerender.absolute-limit-y", AnimationPrerenderAbsoluteLimitY, uint32_t, 4096);
DECL_GFX_PREF(Live, "layout.css.scroll-behavior.damping-ratio", ScrollBehaviorDampingRatio, float, 1.0f);
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -604,16 +604,19 @@ pref("layers.amd-switchable-gfx.enabled"
pref("layers.async-pan-zoom.enabled", true);
// Whether to enable event region building during painting
pref("layout.event-regions.enabled", false);
// Whether to enable arbitrary layer geometry for OpenGL compositor
pref("layers.geometry.opengl.enabled", true);
+// Whether to enable arbitrary layer geometry for Basic compositor
+pref("layers.geometry.basic.enabled", true);
+
// APZ preferences. For documentation/details on what these prefs do, check
// gfx/layers/apz/src/AsyncPanZoomController.cpp.
pref("apz.allow_checkerboarding", true);
pref("apz.allow_immediate_handoff", true);
pref("apz.allow_zooming", false);
// Whether to lock touch scrolling to one axis at a time
// 0 = FREE (No locking at all)