From 94420297e4b82f8c1e037cae84a958ba6c5785b4 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 5 Feb 2014 08:39:02 -0800 Subject: [PATCH] Bug 947045 - Use Xlib surfaces in basic compositor (r=mattwoodrow) --- gfx/layers/basic/TextureClientX11.cpp | 149 +++++++++++++++++++++++ gfx/layers/basic/TextureClientX11.h | 68 +++++++++++ gfx/layers/basic/TextureHostBasic.cpp | 10 ++ gfx/layers/basic/TextureHostX11.cpp | 111 +++++++++++++++++ gfx/layers/basic/TextureHostX11.h | 76 ++++++++++++ gfx/layers/client/CompositableClient.cpp | 14 +++ gfx/layers/moz.build | 4 + 7 files changed, 432 insertions(+) create mode 100644 gfx/layers/basic/TextureClientX11.cpp create mode 100644 gfx/layers/basic/TextureClientX11.h create mode 100644 gfx/layers/basic/TextureHostX11.cpp create mode 100644 gfx/layers/basic/TextureHostX11.h diff --git a/gfx/layers/basic/TextureClientX11.cpp b/gfx/layers/basic/TextureClientX11.cpp new file mode 100644 index 000000000000..14285c1b0453 --- /dev/null +++ b/gfx/layers/basic/TextureClientX11.cpp @@ -0,0 +1,149 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// * 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/. */ +#include "mozilla/layers/TextureClientX11.h" +#include "mozilla/layers/CompositableClient.h" +#include "mozilla/layers/CompositableForwarder.h" +#include "mozilla/layers/ISurfaceAllocator.h" +#include "mozilla/layers/ShadowLayerUtilsX11.h" +#include "mozilla/gfx/2D.h" +#include "gfxXlibSurface.h" +#include "gfx2DGlue.h" + +#include "mozilla/X11Util.h" +#include + +using namespace mozilla; +using namespace mozilla::gfx; +using namespace mozilla::layers; + +TextureClientX11::TextureClientX11(SurfaceFormat aFormat, TextureFlags aFlags) + : mFormat(aFormat), + mTextureFlags(aFlags) +{ + MOZ_COUNT_CTOR(TextureClientX11); +} + +TextureClientX11::~TextureClientX11() +{ + MOZ_COUNT_DTOR(TextureClientX11); +} + +bool +TextureClientX11::IsAllocated() const +{ + return !!mSurface; +} + +bool +TextureClientX11::Lock(OpenMode aMode) +{ + // XXX - Turn this into a fatal assertion as soon as Bug 952507 is fixed + NS_WARN_IF_FALSE(!mLocked, "The TextureClient is already Locked!"); + mLocked = true; + return IsValid() && IsAllocated(); +} + +void +TextureClientX11::Unlock() +{ + // XXX - Turn this into a fatal assertion as soon as Bug 952507 is fixed + NS_WARN_IF_FALSE(mLocked, "The TextureClient is already Unlocked!"); + mLocked = false; + + if (mSurface) { + FinishX(DefaultXDisplay()); + } +} + +bool +TextureClientX11::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) +{ + MOZ_ASSERT(IsValid()); + if (!mSurface) { + return false; + } + + aOutDescriptor = SurfaceDescriptorX11(mSurface); + return true; +} + +TextureClientData* +TextureClientX11::DropTextureData() +{ + MOZ_ASSERT(!(mFlags & TEXTURE_DEALLOCATE_CLIENT)); + return nullptr; +} + +bool +TextureClientX11::UpdateSurface(gfxASurface* aSurface) +{ + MOZ_ASSERT(IsValid()); + + if (gfxPlatform::GetPlatform()->SupportsAzureContent()) { + RefPtr dt = GetAsDrawTarget(); + if (!dt) { + return false; + } + + RefPtr source = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt, aSurface); + dt->CopySurface(source, IntRect(IntPoint(), GetSize()), IntPoint()); + } else { + if (!mSurface) { + return false; + } + + nsRefPtr ctx = new gfxContext(mSurface.get()); + ctx->SetOperator(gfxContext::OPERATOR_SOURCE); + ctx->DrawSurface(aSurface, mSurface->GetSize()); + } + + return true; +} + +already_AddRefed +TextureClientX11::GetAsSurface() +{ + MOZ_ASSERT(IsValid()); + if (!mSurface) { + return nullptr; + } + + nsRefPtr temp = mSurface.get(); + return temp.forget(); +} + +bool +TextureClientX11::AllocateForSurface(IntSize aSize, TextureAllocationFlags aTextureFlags) +{ + MOZ_ASSERT(IsValid()); + //MOZ_ASSERT(mFormat != gfx::FORMAT_YUV, "This TextureClient cannot use YCbCr data"); + + gfxContentType contentType = ContentForFormat(mFormat); + gfxIntSize size = ThebesIntSize(aSize); + nsRefPtr surface = gfxPlatform::GetPlatform()->CreateOffscreenSurface(size, contentType); + if (!surface || surface->GetType() != gfxSurfaceType::Xlib) { + NS_ERROR("creating Xlib surface failed!"); + return false; + } + + mSize = aSize; + mSurface = static_cast(surface.get()); + + // The host is always responsible for freeing the pixmap. + mSurface->ReleasePixmap(); + return true; +} + +TemporaryRef +TextureClientX11::GetAsDrawTarget() +{ + MOZ_ASSERT(IsValid()); + if (!mSurface) { + return nullptr; + } + + IntSize size = ToIntSize(mSurface->GetSize()); + return Factory::CreateDrawTargetForCairoSurface(mSurface->CairoSurface(), size); +} diff --git a/gfx/layers/basic/TextureClientX11.h b/gfx/layers/basic/TextureClientX11.h new file mode 100644 index 000000000000..91aa446d30c7 --- /dev/null +++ b/gfx/layers/basic/TextureClientX11.h @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// * 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_TEXTURECLIENT_X11_H +#define MOZILLA_GFX_TEXTURECLIENT_X11_H + +#include "mozilla/layers/TextureClient.h" +#include "ISurfaceAllocator.h" // For IsSurfaceDescriptorValid +#include "mozilla/layers/ShadowLayerUtilsX11.h" + +namespace mozilla { +namespace layers { + +/** + * A TextureClient implementation based on Xlib. + */ +class TextureClientX11 + : public TextureClient, + public TextureClientSurface, + public TextureClientDrawTarget +{ + public: + TextureClientX11(gfx::SurfaceFormat format, TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT); + ~TextureClientX11(); + + // TextureClient + + TextureClientSurface* AsTextureClientSurface() MOZ_OVERRIDE { return this; } + TextureClientDrawTarget* AsTextureClientDrawTarget() MOZ_OVERRIDE { return this; } + + bool IsAllocated() const MOZ_OVERRIDE; + bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE; + TextureClientData* DropTextureData() MOZ_OVERRIDE; + gfx::IntSize GetSize() const { + return mSize; + } + + bool Lock(OpenMode aMode) MOZ_OVERRIDE; + void Unlock() MOZ_OVERRIDE; + bool IsLocked() const MOZ_OVERRIDE { return mLocked; } + + // TextureClientSurface + + bool UpdateSurface(gfxASurface* aSurface) MOZ_OVERRIDE; + already_AddRefed GetAsSurface() MOZ_OVERRIDE; + bool AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags flags) MOZ_OVERRIDE; + + // TextureClientDrawTarget + + TemporaryRef GetAsDrawTarget() MOZ_OVERRIDE; + gfx::SurfaceFormat GetFormat() const { + return mFormat; + } + + private: + gfx::SurfaceFormat mFormat; + TextureFlags mTextureFlags; + gfx::IntSize mSize; + RefPtr mSurface; + bool mLocked; +}; + +} // namespace layers +} // namespace mozilla + +#endif diff --git a/gfx/layers/basic/TextureHostBasic.cpp b/gfx/layers/basic/TextureHostBasic.cpp index 556e97c22711..f6160e279749 100644 --- a/gfx/layers/basic/TextureHostBasic.cpp +++ b/gfx/layers/basic/TextureHostBasic.cpp @@ -4,6 +4,9 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "TextureHostBasic.h" +#ifdef MOZ_X11 +#include "TextureHostX11.h" +#endif #include "MacIOSurfaceTextureHostBasic.h" using namespace mozilla::gl; @@ -25,6 +28,13 @@ CreateTextureHostBasic(const SurfaceDescriptor& aDesc, return result; } #endif +#ifdef MOZ_X11 + if (aDesc.type() == SurfaceDescriptor::TSurfaceDescriptorX11) { + const SurfaceDescriptorX11& desc = aDesc.get_SurfaceDescriptorX11(); + RefPtr result = new TextureHostX11(aFlags, desc); + return result; + } +#endif return CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags); } diff --git a/gfx/layers/basic/TextureHostX11.cpp b/gfx/layers/basic/TextureHostX11.cpp new file mode 100644 index 000000000000..b3fb168479d6 --- /dev/null +++ b/gfx/layers/basic/TextureHostX11.cpp @@ -0,0 +1,111 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * 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/. */ + +#include "TextureHostX11.h" +#include "mozilla/layers/BasicCompositor.h" +#include "gfxXlibSurface.h" +#include "gfx2DGlue.h" + +using namespace mozilla; +using namespace mozilla::layers; +using namespace mozilla::gfx; + +static inline SurfaceFormat +ContentTypeToSurfaceFormat(gfxContentType type) +{ + switch (type) { + case gfxContentType::COLOR: + return SurfaceFormat::B8G8R8X8; + case gfxContentType::ALPHA: + return SurfaceFormat::A8; + case gfxContentType::COLOR_ALPHA: + return SurfaceFormat::B8G8R8A8; + default: + return SurfaceFormat::UNKNOWN; + } +} + +TextureSourceX11::TextureSourceX11(BasicCompositor* aCompositor, gfxXlibSurface* aSurface) + : mCompositor(aCompositor), + mSurface(aSurface) +{ +} + +IntSize +TextureSourceX11::GetSize() const +{ + return ToIntSize(mSurface->GetSize()); +} + +SurfaceFormat +TextureSourceX11::GetFormat() const +{ + return ContentTypeToSurfaceFormat(mSurface->GetContentType()); +} + +SourceSurface* +TextureSourceX11::GetSurface() +{ + if (!mSourceSurface) { + mSourceSurface = + Factory::CreateSourceSurfaceForCairoSurface(mSurface->CairoSurface(), GetFormat()); + } + return mSourceSurface; +} + +void +TextureSourceX11::SetCompositor(Compositor* aCompositor) +{ + BasicCompositor* compositor = static_cast(aCompositor); + mCompositor = compositor; +} + +TextureHostX11::TextureHostX11(TextureFlags aFlags, + const SurfaceDescriptorX11& aDescriptor) + : TextureHost(aFlags) +{ + nsRefPtr surface = aDescriptor.OpenForeign(); + mSurface = surface.get(); + + // The host always frees the pixmap. + MOZ_ASSERT(!(aFlags & TEXTURE_DEALLOCATE_CLIENT)); + mSurface->TakePixmap(); +} + +bool +TextureHostX11::Lock() +{ + if (!mCompositor) { + return false; + } + + if (!mTextureSource) { + mTextureSource = new TextureSourceX11(mCompositor, mSurface); + } + + return true; +} + +void +TextureHostX11::SetCompositor(Compositor* aCompositor) +{ + BasicCompositor* compositor = static_cast(aCompositor); + mCompositor = compositor; + if (mTextureSource) { + mTextureSource->SetCompositor(compositor); + } +} + +SurfaceFormat +TextureHostX11::GetFormat() const +{ + return ContentTypeToSurfaceFormat(mSurface->GetContentType()); +} + +IntSize +TextureHostX11::GetSize() const +{ + return ToIntSize(mSurface->GetSize()); +} diff --git a/gfx/layers/basic/TextureHostX11.h b/gfx/layers/basic/TextureHostX11.h new file mode 100644 index 000000000000..c744e6e3dd80 --- /dev/null +++ b/gfx/layers/basic/TextureHostX11.h @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * 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_TEXTUREHOSTX11__H +#define MOZILLA_GFX_TEXTUREHOSTX11__H + +#include "mozilla/layers/TextureHostBasic.h" +#include "mozilla/gfx/2D.h" + +namespace mozilla { +namespace layers { + +class BasicCompositor; + +// TextureSource for Xlib-backed surfaces. +class TextureSourceX11 + : public TextureSourceBasic, + public NewTextureSource +{ +public: + TextureSourceX11(BasicCompositor* aCompositor, gfxXlibSurface* aSurface); + + virtual TextureSourceX11* AsSourceBasic() MOZ_OVERRIDE { return this; } + + virtual gfx::IntSize GetSize() const MOZ_OVERRIDE; + virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE; + virtual gfx::SourceSurface* GetSurface() MOZ_OVERRIDE; + + virtual void DeallocateDeviceData() MOZ_OVERRIDE { } + + virtual void SetCompositor(Compositor* aCompositor); + +protected: + BasicCompositor* mCompositor; + RefPtr mSurface; + RefPtr mSourceSurface; +}; + +// TextureSource for Xlib-backed TextureSources. +class TextureHostX11 : public TextureHost +{ +public: + TextureHostX11(TextureFlags aFlags, + const SurfaceDescriptorX11& aDescriptor); + + virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE; + virtual bool Lock() MOZ_OVERRIDE; + virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE; + virtual gfx::IntSize GetSize() const MOZ_OVERRIDE; + + virtual NewTextureSource* GetTextureSources() MOZ_OVERRIDE + { + return mTextureSource; + } + + virtual TemporaryRef GetAsSurface() MOZ_OVERRIDE + { + return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING) + } + +#ifdef MOZ_LAYERS_HAVE_LOG + virtual const char* Name() { return "TextureHostX11"; } +#endif + +protected: + BasicCompositor* mCompositor; + RefPtr mTextureSource; + RefPtr mSurface; +}; + +} // namespace layers +} // namespace mozilla + +#endif // MOZILLA_GFX_TEXTUREHOSTX11__H diff --git a/gfx/layers/client/CompositableClient.cpp b/gfx/layers/client/CompositableClient.cpp index c5317c997e4b..cc4cfc861009 100644 --- a/gfx/layers/client/CompositableClient.cpp +++ b/gfx/layers/client/CompositableClient.cpp @@ -17,6 +17,9 @@ #include "gfxWindowsPlatform.h" #include "gfx2DGlue.h" #endif +#ifdef MOZ_X11 +#include "mozilla/layers/TextureClientX11.h" +#endif using namespace mozilla::gfx; @@ -212,6 +215,17 @@ CompositableClient::CreateTextureClientForDrawing(SurfaceFormat aFormat, } } #endif + +#ifdef MOZ_X11 + LayersBackend parentBackend = GetForwarder()->GetCompositorBackendType(); + if (parentBackend == LayersBackend::LAYERS_BASIC && + gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType() == gfxSurfaceType::Xlib && + !(aTextureFlags & TEXTURE_ALLOC_FALLBACK)) + { + result = new TextureClientX11(aFormat, aTextureFlags); + } +#endif + // Can't do any better than a buffer texture client. if (!result) { result = CreateBufferTextureClient(aFormat, aTextureFlags); diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build index 16cccb879d0d..54b8c8f33048 100644 --- a/gfx/layers/moz.build +++ b/gfx/layers/moz.build @@ -157,9 +157,13 @@ EXPORTS.mozilla.layers += [ if CONFIG['MOZ_X11']: EXPORTS.mozilla.layers += [ + 'basic/TextureClientX11.h', + 'basic/TextureHostX11.h', 'ipc/ShadowLayerUtilsX11.h', ] SOURCES += [ + 'basic/TextureClientX11.cpp', + 'basic/TextureHostX11.cpp', 'ipc/ShadowLayerUtilsX11.cpp' ]