зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1167235 - Part 1 - Render canvas2D into TextureClient directly. r=Bas
This commit is contained in:
Родитель
ef48def7da
Коммит
9367516d33
|
@ -85,6 +85,7 @@
|
|||
#include "mozilla/EndianUtils.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/gfx/Helpers.h"
|
||||
#include "mozilla/gfx/Tools.h"
|
||||
#include "mozilla/gfx/PathHelpers.h"
|
||||
#include "mozilla/gfx/DataSurfaceHelpers.h"
|
||||
#include "mozilla/gfx/PatternHelpers.h"
|
||||
|
@ -120,6 +121,7 @@
|
|||
#include "CanvasUtils.h"
|
||||
#include "mozilla/StyleSetHandle.h"
|
||||
#include "mozilla/StyleSetHandleInlines.h"
|
||||
#include "mozilla/layers/CanvasClient.h"
|
||||
|
||||
#undef free // apparently defined by some windows header, clashing with a free()
|
||||
// method in SkTypes.h
|
||||
|
@ -223,10 +225,32 @@ protected:
|
|||
Point mEnd;
|
||||
};
|
||||
|
||||
bool
|
||||
CanvasRenderingContext2D::PatternIsOpaque(CanvasRenderingContext2D::Style aStyle) const
|
||||
{
|
||||
const ContextState& state = CurrentState();
|
||||
if (state.globalAlpha < 1.0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (state.patternStyles[aStyle] && state.patternStyles[aStyle]->mSurface) {
|
||||
return IsOpaqueFormat(state.patternStyles[aStyle]->mSurface->GetFormat());
|
||||
}
|
||||
|
||||
// TODO: for gradient patterns we could check that all stops are opaque
|
||||
// colors.
|
||||
|
||||
if (!state.gradientStyles[aStyle]) {
|
||||
// it's a color pattern.
|
||||
return Color::FromABGR(state.colorStyles[aStyle]).a >= 1.0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// This class is named 'GeneralCanvasPattern' instead of just
|
||||
// 'GeneralPattern' to keep Windows PGO builds from confusing the
|
||||
// GeneralPattern class in gfxContext.cpp with this one.
|
||||
|
||||
class CanvasGeneralPattern
|
||||
{
|
||||
public:
|
||||
|
@ -1276,6 +1300,8 @@ bool CanvasRenderingContext2D::SwitchRenderingMode(RenderingMode aRenderingMode)
|
|||
|
||||
RefPtr<SourceSurface> snapshot;
|
||||
Matrix transform;
|
||||
RefPtr<PersistentBufferProvider> oldBufferProvider = mBufferProvider;
|
||||
AutoReturnSnapshot autoReturn(nullptr);
|
||||
|
||||
if (mTarget) {
|
||||
snapshot = mTarget->Snapshot();
|
||||
|
@ -1285,14 +1311,16 @@ bool CanvasRenderingContext2D::SwitchRenderingMode(RenderingMode aRenderingMode)
|
|||
// When mBufferProvider is true but we have no mTarget, our current state's
|
||||
// transform is always valid. See ReturnTarget().
|
||||
transform = CurrentState().transform;
|
||||
snapshot = mBufferProvider->GetSnapshot();
|
||||
snapshot = mBufferProvider->BorrowSnapshot();
|
||||
autoReturn.mBufferProvider = mBufferProvider;
|
||||
autoReturn.mSnapshot = &snapshot;
|
||||
}
|
||||
mTarget = nullptr;
|
||||
mBufferProvider = nullptr;
|
||||
mResetLayer = true;
|
||||
|
||||
// Recreate target using the new rendering mode
|
||||
RenderingMode attemptedMode = EnsureTarget(aRenderingMode);
|
||||
RenderingMode attemptedMode = EnsureTarget(nullptr, aRenderingMode);
|
||||
if (!IsTargetValid())
|
||||
return false;
|
||||
|
||||
|
@ -1425,7 +1453,8 @@ CanvasRenderingContext2D::CheckSizeForSkiaGL(IntSize aSize) {
|
|||
}
|
||||
|
||||
CanvasRenderingContext2D::RenderingMode
|
||||
CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
|
||||
CanvasRenderingContext2D::EnsureTarget(const gfx::Rect* aCoveredRect,
|
||||
RenderingMode aRenderingMode)
|
||||
{
|
||||
// This would make no sense, so make sure we don't get ourselves in a mess
|
||||
MOZ_ASSERT(mRenderingMode != RenderingMode::DefaultBackendMode);
|
||||
|
@ -1437,8 +1466,21 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
|
|||
}
|
||||
|
||||
if (mBufferProvider && mode == mRenderingMode) {
|
||||
mTarget = mBufferProvider->GetDT(IntRect(IntPoint(), IntSize(mWidth, mHeight)));
|
||||
gfx::Rect rect(0, 0, mWidth, mHeight);
|
||||
if (aCoveredRect && CurrentState().transform.TransformBounds(*aCoveredRect).Contains(rect)) {
|
||||
mTarget = mBufferProvider->BorrowDrawTarget(IntRect());
|
||||
} else {
|
||||
mTarget = mBufferProvider->BorrowDrawTarget(IntRect(0, 0, mWidth, mHeight));
|
||||
}
|
||||
|
||||
if (mTarget) {
|
||||
// Restore clip and transform.
|
||||
mTarget->SetTransform(CurrentState().transform);
|
||||
for (uint32_t i = 0; i < mStyleStack.Length(); i++) {
|
||||
for (uint32_t c = 0; c < mStyleStack[i].clipsPushed.Length(); c++) {
|
||||
mTarget->PushClip(mStyleStack[i].clipsPushed[c]);
|
||||
}
|
||||
}
|
||||
return mRenderingMode;
|
||||
} else {
|
||||
mBufferProvider = nullptr;
|
||||
|
@ -1495,7 +1537,7 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
|
|||
}
|
||||
|
||||
if (mBufferProvider) {
|
||||
mTarget = mBufferProvider->GetDT(IntRect(IntPoint(), IntSize(mWidth, mHeight)));
|
||||
mTarget = mBufferProvider->BorrowDrawTarget(IntRect(IntPoint(), IntSize(mWidth, mHeight)));
|
||||
} else if (!mTarget) {
|
||||
mTarget = gfxPlatform::GetPlatform()->CreateOffscreenCanvasDrawTarget(size, format);
|
||||
mode = RenderingMode::SoftwareBackendMode;
|
||||
|
@ -1623,7 +1665,12 @@ CanvasRenderingContext2D::ReturnTarget()
|
|||
{
|
||||
if (mTarget && mBufferProvider) {
|
||||
CurrentState().transform = mTarget->GetTransform();
|
||||
mBufferProvider->ReturnAndUseDT(mTarget.forget());
|
||||
for (uint32_t i = 0; i < mStyleStack.Length(); i++) {
|
||||
for (uint32_t c = 0; c < mStyleStack[i].clipsPushed.Length(); c++) {
|
||||
mTarget->PopClip();
|
||||
}
|
||||
}
|
||||
mBufferProvider->ReturnDrawTarget(mTarget.forget());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2598,9 +2645,11 @@ CanvasRenderingContext2D::ClearRect(double aX, double aY, double aW,
|
|||
return;
|
||||
}
|
||||
|
||||
EnsureTarget();
|
||||
gfx::Rect clearRect(aX, aY, aW, aH);
|
||||
|
||||
mTarget->ClearRect(gfx::Rect(aX, aY, aW, aH));
|
||||
EnsureTarget(&clearRect);
|
||||
|
||||
mTarget->ClearRect(clearRect);
|
||||
|
||||
RedrawUser(gfxRect(aX, aY, aW, aH));
|
||||
}
|
||||
|
@ -2661,18 +2710,22 @@ CanvasRenderingContext2D::FillRect(double aX, double aY, double aW,
|
|||
}
|
||||
}
|
||||
|
||||
gfx::Rect bounds;
|
||||
CompositionOp op = UsedOperation();
|
||||
bool discardContent = PatternIsOpaque(Style::FILL)
|
||||
&& (op == CompositionOp::OP_OVER || op == CompositionOp::OP_DEST_OUT);
|
||||
|
||||
EnsureTarget();
|
||||
const gfx::Rect fillRect(aX, aY, aW, aH);
|
||||
EnsureTarget(discardContent ? &fillRect : nullptr);
|
||||
|
||||
gfx::Rect bounds;
|
||||
if (NeedToCalculateBounds()) {
|
||||
bounds = gfx::Rect(aX, aY, aW, aH);
|
||||
bounds = mTarget->GetTransform().TransformBounds(bounds);
|
||||
bounds = mTarget->GetTransform().TransformBounds(fillRect);
|
||||
}
|
||||
|
||||
AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
|
||||
FillRect(gfx::Rect(aX, aY, aW, aH),
|
||||
CanvasGeneralPattern().ForStyle(this, Style::FILL, mTarget),
|
||||
DrawOptions(state.globalAlpha, UsedOperation()));
|
||||
DrawOptions(state.globalAlpha, op));
|
||||
|
||||
RedrawUser(gfxRect(aX, aY, aW, aH));
|
||||
}
|
||||
|
@ -5646,7 +5699,14 @@ CanvasRenderingContext2D::GetBufferProvider(LayerManager* aManager)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
mBufferProvider = new PersistentBufferProviderBasic(mTarget);
|
||||
if (aManager) {
|
||||
mBufferProvider = aManager->CreatePersistentBufferProvider(gfx::IntSize(mWidth, mHeight),
|
||||
GetSurfaceFormat());
|
||||
}
|
||||
|
||||
if (!mBufferProvider) {
|
||||
mBufferProvider = new PersistentBufferProviderBasic(mTarget);
|
||||
}
|
||||
|
||||
return mBufferProvider;
|
||||
}
|
||||
|
|
|
@ -635,7 +635,8 @@ protected:
|
|||
*
|
||||
* Returns the actual rendering mode being used by the created target.
|
||||
*/
|
||||
RenderingMode EnsureTarget(RenderingMode aRenderMode = RenderingMode::DefaultBackendMode);
|
||||
RenderingMode EnsureTarget(const gfx::Rect* aCoveredRect = nullptr,
|
||||
RenderingMode aRenderMode = RenderingMode::DefaultBackendMode);
|
||||
|
||||
/**
|
||||
* Disposes an old target and prepares to lazily create a new target.
|
||||
|
@ -661,6 +662,12 @@ protected:
|
|||
*/
|
||||
mozilla::gfx::SurfaceFormat GetSurfaceFormat() const;
|
||||
|
||||
/**
|
||||
* Returns true if we know for sure that the pattern for a given style is opaque.
|
||||
* Usefull to know if we can discard the content below in certain situations.
|
||||
*/
|
||||
bool PatternIsOpaque(Style aStyle) const;
|
||||
|
||||
/**
|
||||
* Update CurrentState().filter with the filter description for
|
||||
* CurrentState().filterChain.
|
||||
|
|
|
@ -98,6 +98,22 @@ BytesPerPixel(SurfaceFormat aFormat)
|
|||
}
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsOpaqueFormat(SurfaceFormat aFormat) {
|
||||
switch (aFormat) {
|
||||
case SurfaceFormat::B8G8R8X8:
|
||||
case SurfaceFormat::R8G8B8X8:
|
||||
case SurfaceFormat::X8R8G8B8:
|
||||
case SurfaceFormat::YUV:
|
||||
case SurfaceFormat::NV12:
|
||||
case SurfaceFormat::YUV422:
|
||||
case SurfaceFormat::R5G6B5_UINT16:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, int alignment = 16>
|
||||
struct AlignedArray
|
||||
{
|
||||
|
|
|
@ -85,10 +85,21 @@ CopyableCanvasLayer::IsDataValid(const Data& aData)
|
|||
void
|
||||
CopyableCanvasLayer::UpdateTarget(DrawTarget* aDestTarget)
|
||||
{
|
||||
AutoReturnSnapshot autoReturn;
|
||||
|
||||
if (mAsyncRenderer) {
|
||||
mSurface = mAsyncRenderer->GetSurface();
|
||||
} else if (!mGLFrontbuffer && mBufferProvider) {
|
||||
mSurface = mBufferProvider->GetSnapshot();
|
||||
mSurface = mBufferProvider->BorrowSnapshot();
|
||||
if (aDestTarget) {
|
||||
// If !aDestTarget we'll end up painting using mSurface later,
|
||||
// so we can't return it to the provider (note that this will trigger a
|
||||
// copy of the snapshot behind the scenes when the provider is unlocked).
|
||||
autoReturn.mSnapshot = &mSurface;
|
||||
}
|
||||
// Either way we need to call ReturnSnapshot because ther may be an
|
||||
// underlying TextureClient that has to be unlocked.
|
||||
autoReturn.mBufferProvider = mBufferProvider;
|
||||
}
|
||||
|
||||
if (!mGLContext && aDestTarget) {
|
||||
|
@ -99,6 +110,7 @@ CopyableCanvasLayer::UpdateTarget(DrawTarget* aDestTarget)
|
|||
IntPoint(0, 0));
|
||||
mSurface = nullptr;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -177,17 +177,12 @@ LayerManager::CreatePersistentBufferProvider(const mozilla::gfx::IntSize &aSize,
|
|||
mozilla::gfx::SurfaceFormat aFormat)
|
||||
{
|
||||
RefPtr<PersistentBufferProviderBasic> bufferProvider =
|
||||
new PersistentBufferProviderBasic(aSize, aFormat,
|
||||
gfxPlatform::GetPlatform()->GetPreferredCanvasBackend());
|
||||
PersistentBufferProviderBasic::Create(aSize, aFormat,
|
||||
gfxPlatform::GetPlatform()->GetPreferredCanvasBackend());
|
||||
|
||||
if (!bufferProvider->IsValid()) {
|
||||
bufferProvider =
|
||||
new PersistentBufferProviderBasic(aSize, aFormat,
|
||||
gfxPlatform::GetPlatform()->GetFallbackCanvasBackend());
|
||||
}
|
||||
|
||||
if (!bufferProvider->IsValid()) {
|
||||
return nullptr;
|
||||
if (!bufferProvider) {
|
||||
bufferProvider = PersistentBufferProviderBasic::Create(aSize, aFormat,
|
||||
gfxPlatform::GetPlatform()->GetFallbackCanvasBackend());
|
||||
}
|
||||
|
||||
return bufferProvider.forget();
|
||||
|
|
|
@ -16,10 +16,215 @@ using namespace gfx;
|
|||
|
||||
namespace layers {
|
||||
|
||||
PersistentBufferProviderBasic::PersistentBufferProviderBasic(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
gfx::BackendType aBackend)
|
||||
PersistentBufferProviderBasic::PersistentBufferProviderBasic(DrawTarget* aDt)
|
||||
: mDrawTarget(aDt)
|
||||
{
|
||||
mDrawTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForBackend(aBackend, aSize, aFormat);
|
||||
MOZ_COUNT_CTOR(PersistentBufferProviderBasic);
|
||||
}
|
||||
|
||||
PersistentBufferProviderBasic::~PersistentBufferProviderBasic()
|
||||
{
|
||||
MOZ_COUNT_DTOR(PersistentBufferProviderBasic);
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::DrawTarget>
|
||||
PersistentBufferProviderBasic::BorrowDrawTarget(const gfx::IntRect& aPersistedRect)
|
||||
{
|
||||
MOZ_ASSERT(!mSnapshot);
|
||||
RefPtr<gfx::DrawTarget> dt(mDrawTarget);
|
||||
return dt.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
PersistentBufferProviderBasic::ReturnDrawTarget(already_AddRefed<gfx::DrawTarget> aDT)
|
||||
{
|
||||
RefPtr<gfx::DrawTarget> dt(aDT);
|
||||
MOZ_ASSERT(mDrawTarget == dt);
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::SourceSurface>
|
||||
PersistentBufferProviderBasic::BorrowSnapshot()
|
||||
{
|
||||
mSnapshot = mDrawTarget->Snapshot();
|
||||
RefPtr<SourceSurface> snapshot = mSnapshot;
|
||||
return snapshot.forget();
|
||||
}
|
||||
|
||||
void
|
||||
PersistentBufferProviderBasic::ReturnSnapshot(already_AddRefed<gfx::SourceSurface> aSnapshot)
|
||||
{
|
||||
RefPtr<SourceSurface> snapshot = aSnapshot;
|
||||
MOZ_ASSERT(!snapshot || snapshot == mSnapshot);
|
||||
mSnapshot = nullptr;
|
||||
}
|
||||
|
||||
//static
|
||||
already_AddRefed<PersistentBufferProviderBasic>
|
||||
PersistentBufferProviderBasic::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
gfx::BackendType aBackend)
|
||||
{
|
||||
RefPtr<DrawTarget> dt = gfxPlatform::GetPlatform()->CreateDrawTargetForBackend(aBackend, aSize, aFormat);
|
||||
|
||||
if (!dt) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<PersistentBufferProviderBasic> provider =
|
||||
new PersistentBufferProviderBasic(dt);
|
||||
|
||||
return provider.forget();
|
||||
}
|
||||
|
||||
|
||||
//static
|
||||
already_AddRefed<PersistentBufferProviderShared>
|
||||
PersistentBufferProviderShared::Create(gfx::IntSize aSize,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
CompositableForwarder* aFwd)
|
||||
{
|
||||
if (!aFwd || !aFwd->IPCOpen()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<TextureClient> texture = TextureClient::CreateForDrawing(
|
||||
aFwd, aFormat, aSize,
|
||||
BackendSelector::Canvas,
|
||||
TextureFlags::IMMEDIATE_UPLOAD,
|
||||
TextureAllocationFlags::ALLOC_DEFAULT
|
||||
);
|
||||
|
||||
if (!texture) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<PersistentBufferProviderShared> provider =
|
||||
new PersistentBufferProviderShared(aSize, aFormat, aFwd, texture);
|
||||
return provider.forget();
|
||||
}
|
||||
|
||||
PersistentBufferProviderShared::PersistentBufferProviderShared(gfx::IntSize aSize,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
CompositableForwarder* aFwd,
|
||||
RefPtr<TextureClient>& aTexture)
|
||||
|
||||
: mSize(aSize)
|
||||
, mFormat(aFormat)
|
||||
, mFwd(aFwd)
|
||||
, mBack(aTexture.forget())
|
||||
{
|
||||
MOZ_COUNT_CTOR(PersistentBufferProviderShared);
|
||||
}
|
||||
|
||||
PersistentBufferProviderShared::~PersistentBufferProviderShared()
|
||||
{
|
||||
MOZ_COUNT_DTOR(PersistentBufferProviderShared);
|
||||
|
||||
mDrawTarget = nullptr;
|
||||
if (mBack && mBack->IsLocked()) {
|
||||
mBack->Unlock();
|
||||
}
|
||||
if (mFront && mFront->IsLocked()) {
|
||||
mFront->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::DrawTarget>
|
||||
PersistentBufferProviderShared::BorrowDrawTarget(const gfx::IntRect& aPersistedRect)
|
||||
{
|
||||
if (!mFwd->IPCOpen()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!mDrawTarget) {
|
||||
if (!mBack) {
|
||||
mBack = TextureClient::CreateForDrawing(
|
||||
mFwd, mFormat, mSize,
|
||||
BackendSelector::Canvas,
|
||||
TextureFlags::IMMEDIATE_UPLOAD,
|
||||
TextureAllocationFlags::ALLOC_DEFAULT
|
||||
);
|
||||
}
|
||||
|
||||
if (!mBack) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!mBack->Lock(OpenMode::OPEN_READ_WRITE)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!aPersistedRect.IsEmpty() && mFront
|
||||
&& mFront->Lock(OpenMode::OPEN_READ)) {
|
||||
|
||||
DebugOnly<bool> success = mFront->CopyToTextureClient(mBack, &aPersistedRect, nullptr);
|
||||
MOZ_ASSERT(success);
|
||||
|
||||
mFront->Unlock();
|
||||
}
|
||||
|
||||
mDrawTarget = mBack->BorrowDrawTarget();
|
||||
if (!mDrawTarget) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<gfx::DrawTarget> dt(mDrawTarget);
|
||||
return dt.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
PersistentBufferProviderShared::ReturnDrawTarget(already_AddRefed<gfx::DrawTarget> aDT)
|
||||
{
|
||||
RefPtr<gfx::DrawTarget> dt(aDT);
|
||||
MOZ_ASSERT(mDrawTarget == dt);
|
||||
|
||||
mDrawTarget = nullptr;
|
||||
dt = nullptr;
|
||||
|
||||
mBack->Unlock();
|
||||
|
||||
mFront = mBack;
|
||||
mBack = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::SourceSurface>
|
||||
PersistentBufferProviderShared::BorrowSnapshot()
|
||||
{
|
||||
if (!mFront || mFront->IsLocked()) {
|
||||
MOZ_ASSERT(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!mFront->Lock(OpenMode::OPEN_READ)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mDrawTarget = mFront->BorrowDrawTarget();
|
||||
|
||||
if (!mDrawTarget) {
|
||||
mFront->Unlock();
|
||||
}
|
||||
|
||||
mSnapshot = mDrawTarget->Snapshot();
|
||||
|
||||
RefPtr<SourceSurface> snapshot = mSnapshot;
|
||||
return snapshot.forget();
|
||||
}
|
||||
|
||||
void
|
||||
PersistentBufferProviderShared::ReturnSnapshot(already_AddRefed<gfx::SourceSurface> aSnapshot)
|
||||
{
|
||||
RefPtr<SourceSurface> snapshot = aSnapshot;
|
||||
MOZ_ASSERT(!snapshot || snapshot == mSnapshot);
|
||||
|
||||
mSnapshot = nullptr;
|
||||
snapshot = nullptr;
|
||||
|
||||
mDrawTarget = nullptr;
|
||||
|
||||
mFront->Unlock();
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -13,6 +13,12 @@
|
|||
#include "mozilla/gfx/Types.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace gfx {
|
||||
class SourceSurface;
|
||||
class DrawTarget;
|
||||
}
|
||||
|
||||
namespace layers {
|
||||
|
||||
class CopyableCanvasLayer;
|
||||
|
@ -38,43 +44,112 @@ public:
|
|||
*
|
||||
* \param aPersistedRect This indicates the area of the DrawTarget that needs
|
||||
* to have remained the same since the call to
|
||||
* ReturnAndUseDT.
|
||||
* ReturnDrawTarget.
|
||||
*/
|
||||
virtual already_AddRefed<gfx::DrawTarget> GetDT(const gfx::IntRect& aPersistedRect) = 0;
|
||||
virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget(const gfx::IntRect& aPersistedRect) = 0;
|
||||
|
||||
/**
|
||||
* Return a DrawTarget to the PersistentBufferProvider and indicate the
|
||||
* contents of this DrawTarget is to be considered current by the
|
||||
* BufferProvider. The caller should forget any references to the DrawTarget.
|
||||
*/
|
||||
virtual bool ReturnAndUseDT(already_AddRefed<gfx::DrawTarget> aDT) = 0;
|
||||
virtual bool ReturnDrawTarget(already_AddRefed<gfx::DrawTarget> aDT) = 0;
|
||||
|
||||
virtual already_AddRefed<gfx::SourceSurface> GetSnapshot() = 0;
|
||||
protected:
|
||||
virtual already_AddRefed<gfx::SourceSurface> BorrowSnapshot() = 0;
|
||||
|
||||
virtual void ReturnSnapshot(already_AddRefed<gfx::SourceSurface> aSnapshot) = 0;
|
||||
|
||||
virtual TextureClient* GetTextureClient() { return nullptr; }
|
||||
};
|
||||
|
||||
|
||||
class PersistentBufferProviderBasic : public PersistentBufferProvider
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProviderBasic)
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProviderBasic, override)
|
||||
|
||||
PersistentBufferProviderBasic(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
gfx::BackendType aBackend);
|
||||
explicit PersistentBufferProviderBasic(gfx::DrawTarget* aTarget) : mDrawTarget(aTarget) {}
|
||||
static already_AddRefed<PersistentBufferProviderBasic>
|
||||
Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, gfx::BackendType aBackend);
|
||||
|
||||
explicit PersistentBufferProviderBasic(gfx::DrawTarget* aTarget);
|
||||
|
||||
virtual LayersBackend GetType() override { return LayersBackend::LAYERS_BASIC; }
|
||||
|
||||
virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget(const gfx::IntRect& aPersistedRect) override;
|
||||
|
||||
virtual bool ReturnDrawTarget(already_AddRefed<gfx::DrawTarget> aDT) override;
|
||||
|
||||
virtual already_AddRefed<gfx::SourceSurface> BorrowSnapshot() override;
|
||||
|
||||
virtual void ReturnSnapshot(already_AddRefed<gfx::SourceSurface> aSnapshot) override;
|
||||
|
||||
bool IsValid() { return !!mDrawTarget; }
|
||||
virtual LayersBackend GetType() { return LayersBackend::LAYERS_BASIC; }
|
||||
already_AddRefed<gfx::DrawTarget> GetDT(const gfx::IntRect& aPersistedRect) {
|
||||
RefPtr<gfx::DrawTarget> dt(mDrawTarget);
|
||||
return dt.forget();
|
||||
}
|
||||
bool ReturnAndUseDT(already_AddRefed<gfx::DrawTarget> aDT) {
|
||||
RefPtr<gfx::DrawTarget> dt(aDT);
|
||||
MOZ_ASSERT(mDrawTarget == dt);
|
||||
return true;
|
||||
}
|
||||
virtual already_AddRefed<gfx::SourceSurface> GetSnapshot() { return mDrawTarget->Snapshot(); }
|
||||
private:
|
||||
~PersistentBufferProviderBasic();
|
||||
|
||||
RefPtr<gfx::DrawTarget> mDrawTarget;
|
||||
RefPtr<gfx::SourceSurface> mSnapshot;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Provides access to a buffer which can be sent to the compositor without
|
||||
* requiring a copy.
|
||||
*/
|
||||
class PersistentBufferProviderShared : public PersistentBufferProvider
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProviderShared, override)
|
||||
|
||||
static already_AddRefed<PersistentBufferProviderShared>
|
||||
Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
CompositableForwarder* aFwd);
|
||||
|
||||
virtual LayersBackend GetType() override { return LayersBackend::LAYERS_CLIENT; }
|
||||
|
||||
virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget(const gfx::IntRect& aPersistedRect) override;
|
||||
|
||||
virtual bool ReturnDrawTarget(already_AddRefed<gfx::DrawTarget> aDT) override;
|
||||
|
||||
virtual already_AddRefed<gfx::SourceSurface> BorrowSnapshot() override;
|
||||
|
||||
virtual void ReturnSnapshot(already_AddRefed<gfx::SourceSurface> aSnapshot) override;
|
||||
|
||||
TextureClient* GetTextureClient() override {
|
||||
return mFront;
|
||||
}
|
||||
|
||||
protected:
|
||||
PersistentBufferProviderShared(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
CompositableForwarder* aFwd,
|
||||
RefPtr<TextureClient>& aTexture);
|
||||
|
||||
~PersistentBufferProviderShared();
|
||||
|
||||
gfx::IntSize mSize;
|
||||
gfx::SurfaceFormat mFormat;
|
||||
RefPtr<CompositableForwarder> mFwd;
|
||||
RefPtr<TextureClient> mFront;
|
||||
RefPtr<TextureClient> mBack;
|
||||
RefPtr<gfx::DrawTarget> mDrawTarget;
|
||||
RefPtr<gfx::SourceSurface > mSnapshot;
|
||||
};
|
||||
|
||||
struct AutoReturnSnapshot
|
||||
{
|
||||
PersistentBufferProvider* mBufferProvider;
|
||||
RefPtr<gfx::SourceSurface>* mSnapshot;
|
||||
|
||||
explicit AutoReturnSnapshot(PersistentBufferProvider* aProvider = nullptr)
|
||||
: mBufferProvider(aProvider)
|
||||
, mSnapshot(nullptr)
|
||||
{}
|
||||
|
||||
~AutoReturnSnapshot()
|
||||
{
|
||||
if (mBufferProvider) {
|
||||
mBufferProvider->ReturnSnapshot(mSnapshot ? mSnapshot->forget() : nullptr);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -66,6 +66,30 @@ CanvasClientBridge::UpdateAsync(AsyncCanvasRenderer* aRenderer)
|
|||
mAsyncID = asyncID;
|
||||
}
|
||||
|
||||
void
|
||||
CanvasClient2D::UpdateFromTexture(TextureClient* aTexture)
|
||||
{
|
||||
MOZ_ASSERT(aTexture);
|
||||
|
||||
if (!aTexture->IsSharedWithCompositor()) {
|
||||
if (!AddTextureClient(aTexture)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mBackBuffer = aTexture;
|
||||
|
||||
AutoTArray<CompositableForwarder::TimedTextureClient,1> textures;
|
||||
CompositableForwarder::TimedTextureClient* t = textures.AppendElement();
|
||||
t->mTextureClient = mBackBuffer;
|
||||
t->mPictureRect = nsIntRect(nsIntPoint(0, 0), aTexture->GetSize());
|
||||
t->mFrameID = mFrameID;
|
||||
t->mInputFrameID = VRManagerChild::Get()->GetInputFrameID();
|
||||
|
||||
GetForwarder()->UseTextures(this, textures);
|
||||
aTexture->SyncWithObject(GetForwarder()->GetSyncObject());
|
||||
}
|
||||
|
||||
void
|
||||
CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
|
||||
{
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "mozilla/layers/CompositorTypes.h" // for TextureInfo, etc
|
||||
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
|
||||
#include "mozilla/layers/TextureClient.h" // for TextureClient, etc
|
||||
#include "mozilla/layers/PersistentBufferProvider.h"
|
||||
|
||||
// Fix X11 header brain damage that conflicts with MaybeOneOf::None
|
||||
#undef None
|
||||
|
@ -76,6 +77,8 @@ public:
|
|||
|
||||
virtual void UpdateAsync(AsyncCanvasRenderer* aRenderer) {}
|
||||
|
||||
virtual void UpdateFromTexture(TextureClient* aTexture) {}
|
||||
|
||||
virtual void Updated() { }
|
||||
|
||||
protected:
|
||||
|
@ -104,6 +107,8 @@ public:
|
|||
|
||||
virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) override;
|
||||
|
||||
virtual void UpdateFromTexture(TextureClient* aBuffer) override;
|
||||
|
||||
virtual bool AddTextureClient(TextureClient* aTexture) override
|
||||
{
|
||||
MOZ_ASSERT((mTextureFlags & aTexture->GetFlags()) == mTextureFlags);
|
||||
|
|
|
@ -130,7 +130,11 @@ ClientCanvasLayer::RenderLayer()
|
|||
Painted();
|
||||
|
||||
FirePreTransactionCallback();
|
||||
mCanvasClient->Update(gfx::IntSize(mBounds.width, mBounds.height), this);
|
||||
if (mBufferProvider && mBufferProvider->GetTextureClient()) {
|
||||
mCanvasClient->UpdateFromTexture(mBufferProvider->GetTextureClient());
|
||||
} else {
|
||||
mCanvasClient->Update(gfx::IntSize(mBounds.width, mBounds.height), this);
|
||||
}
|
||||
|
||||
FireDidTransactionCallback();
|
||||
|
||||
|
|
|
@ -848,6 +848,15 @@ ClientLayerManager::DependsOnStaleDevice() const
|
|||
return gfxPlatform::GetPlatform()->GetDeviceCounter() != mDeviceCounter;
|
||||
}
|
||||
|
||||
|
||||
already_AddRefed<PersistentBufferProvider>
|
||||
ClientLayerManager::CreatePersistentBufferProvider(const gfx::IntSize& aSize,
|
||||
gfx::SurfaceFormat aFormat)
|
||||
{
|
||||
return PersistentBufferProviderShared::Create(aSize, aFormat, AsShadowForwarder());
|
||||
}
|
||||
|
||||
|
||||
ClientLayer::~ClientLayer()
|
||||
{
|
||||
if (HasShadow()) {
|
||||
|
|
|
@ -246,6 +246,9 @@ public:
|
|||
void AddDidCompositeObserver(DidCompositeObserver* aObserver);
|
||||
void RemoveDidCompositeObserver(DidCompositeObserver* aObserver);
|
||||
|
||||
virtual already_AddRefed<PersistentBufferProvider>
|
||||
CreatePersistentBufferProvider(const gfx::IntSize& aSize, gfx::SurfaceFormat aFormat) override;
|
||||
|
||||
protected:
|
||||
enum TransactionPhase {
|
||||
PHASE_NONE, PHASE_CONSTRUCTION, PHASE_DRAWING, PHASE_FORWARD
|
||||
|
|
Загрузка…
Ссылка в новой задаче