diff options
Diffstat (limited to 'gfx/layers/basic/TextureClientX11.cpp')
-rw-r--r-- | gfx/layers/basic/TextureClientX11.cpp | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/gfx/layers/basic/TextureClientX11.cpp b/gfx/layers/basic/TextureClientX11.cpp new file mode 100644 index 000000000..c79ab1a53 --- /dev/null +++ b/gfx/layers/basic/TextureClientX11.cpp @@ -0,0 +1,156 @@ +/* -*- 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 "mozilla/gfx/Logging.h" +#include "gfxXlibSurface.h" +#include "gfx2DGlue.h" + +#include "mozilla/X11Util.h" +#include <X11/Xlib.h> + +using namespace mozilla; +using namespace mozilla::gfx; + +namespace mozilla { +namespace layers { + +X11TextureData::X11TextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, + bool aClientDeallocation, bool aIsCrossProcess, + gfxXlibSurface* aSurface) +: mSize(aSize) +, mFormat(aFormat) +, mSurface(aSurface) +, mClientDeallocation(aClientDeallocation) +, mIsCrossProcess(aIsCrossProcess) +{ + MOZ_ASSERT(mSurface); +} + +bool +X11TextureData::Lock(OpenMode aMode) +{ + return true; +} + +void +X11TextureData::Unlock() +{ + if (mSurface && mIsCrossProcess) { + FinishX(DefaultXDisplay()); + } +} + +void +X11TextureData::FillInfo(TextureData::Info& aInfo) const +{ + aInfo.size = mSize; + aInfo.format = mFormat; + aInfo.supportsMoz2D = true; + aInfo.hasIntermediateBuffer = false; + aInfo.hasSynchronization = false; + aInfo.canExposeMappedData = false; +} + +bool +X11TextureData::Serialize(SurfaceDescriptor& aOutDescriptor) +{ + MOZ_ASSERT(mSurface); + if (!mSurface) { + return false; + } + + if (!mClientDeallocation) { + // Pass to the host the responsibility of freeing the pixmap. ReleasePixmap means + // the underlying pixmap will not be deallocated in mSurface's destructor. + // ToSurfaceDescriptor is at most called once per TextureClient. + mSurface->ReleasePixmap(); + } + + aOutDescriptor = SurfaceDescriptorX11(mSurface); + return true; +} + +already_AddRefed<gfx::DrawTarget> +X11TextureData::BorrowDrawTarget() +{ + MOZ_ASSERT(mSurface); + if (!mSurface) { + return nullptr; + } + + IntSize size = mSurface->GetSize(); + RefPtr<gfx::DrawTarget> dt = Factory::CreateDrawTargetForCairoSurface(mSurface->CairoSurface(), size); + + return dt.forget(); +} + +bool +X11TextureData::UpdateFromSurface(gfx::SourceSurface* aSurface) +{ + RefPtr<DrawTarget> dt = BorrowDrawTarget(); + + if (!dt) { + return false; + } + + dt->CopySurface(aSurface, IntRect(IntPoint(), aSurface->GetSize()), IntPoint()); + + return true; +} + +void +X11TextureData::Deallocate(LayersIPCChannel*) +{ + mSurface = nullptr; +} + +TextureData* +X11TextureData::CreateSimilar(LayersIPCChannel* aAllocator, + LayersBackend aLayersBackend, + TextureFlags aFlags, + TextureAllocationFlags aAllocFlags) const +{ + return X11TextureData::Create(mSize, mFormat, aFlags, aAllocator); +} + +X11TextureData* +X11TextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, + TextureFlags aFlags, LayersIPCChannel* aAllocator) +{ + MOZ_ASSERT(aSize.width >= 0 && aSize.height >= 0); + if (aSize.width <= 0 || aSize.height <= 0 || + aSize.width > XLIB_IMAGE_SIDE_SIZE_LIMIT || + aSize.height > XLIB_IMAGE_SIDE_SIZE_LIMIT) { + gfxDebug() << "Asking for X11 surface of invalid size " << aSize.width << "x" << aSize.height; + return nullptr; + } + gfxImageFormat imageFormat = SurfaceFormatToImageFormat(aFormat); + RefPtr<gfxASurface> surface = gfxPlatform::GetPlatform()->CreateOffscreenSurface(aSize, imageFormat); + if (!surface || surface->GetType() != gfxSurfaceType::Xlib) { + NS_ERROR("creating Xlib surface failed!"); + return nullptr; + } + + gfxXlibSurface* xlibSurface = static_cast<gfxXlibSurface*>(surface.get()); + + bool crossProcess = !aAllocator->IsSameProcess(); + X11TextureData* texture = new X11TextureData(aSize, aFormat, + !!(aFlags & TextureFlags::DEALLOCATE_CLIENT), + crossProcess, + xlibSurface); + if (crossProcess) { + FinishX(DefaultXDisplay()); + } + + return texture; +} + +} // namespace +} // namespace |