2017-10-28 02:10:06 +03:00
|
|
|
/* -*- 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
|
2015-10-15 18:53:33 +03:00
|
|
|
* 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 "BufferTexture.h"
|
2016-06-11 04:49:46 +03:00
|
|
|
#include "libyuv.h"
|
2018-09-25 15:18:58 +03:00
|
|
|
#include "mozilla/Move.h"
|
|
|
|
#include "mozilla/fallible.h"
|
|
|
|
#include "mozilla/gfx/2D.h"
|
|
|
|
#include "mozilla/gfx/Logging.h"
|
|
|
|
#include "mozilla/layers/CompositableForwarder.h"
|
|
|
|
#include "mozilla/layers/ISurfaceAllocator.h"
|
|
|
|
#include "mozilla/layers/ImageDataSerializer.h"
|
2015-10-15 18:53:33 +03:00
|
|
|
|
2016-02-25 16:15:52 +03:00
|
|
|
#ifdef MOZ_WIDGET_GTK
|
|
|
|
# include "gfxPlatformGtk.h"
|
|
|
|
#endif
|
|
|
|
|
2015-10-15 18:53:33 +03:00
|
|
|
namespace mozilla {
|
|
|
|
namespace layers {
|
|
|
|
|
|
|
|
class MemoryTextureData : public BufferTextureData {
|
|
|
|
public:
|
|
|
|
static MemoryTextureData* Create(gfx::IntSize aSize,
|
|
|
|
gfx::SurfaceFormat aFormat,
|
2016-08-23 05:30:14 +03:00
|
|
|
gfx::BackendType aMoz2DBackend,
|
|
|
|
LayersBackend aLayersBackend,
|
|
|
|
TextureFlags aFlags,
|
2015-10-15 18:53:33 +03:00
|
|
|
TextureAllocationFlags aAllocFlags,
|
2019-12-24 10:37:02 +03:00
|
|
|
LayersIPCChannel* aAllocator);
|
2015-10-15 18:53:33 +03:00
|
|
|
|
|
|
|
virtual TextureData* CreateSimilar(
|
2016-09-27 06:22:20 +03:00
|
|
|
LayersIPCChannel* aAllocator, LayersBackend aLayersBackend,
|
2015-10-15 18:53:33 +03:00
|
|
|
TextureFlags aFlags = TextureFlags::DEFAULT,
|
|
|
|
TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override;
|
|
|
|
|
|
|
|
virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;
|
|
|
|
|
2016-09-27 06:22:20 +03:00
|
|
|
virtual void Deallocate(LayersIPCChannel*) override;
|
2015-10-15 18:53:33 +03:00
|
|
|
|
2015-12-16 21:50:58 +03:00
|
|
|
MemoryTextureData(const BufferDescriptor& aDesc,
|
2015-10-15 18:53:33 +03:00
|
|
|
gfx::BackendType aMoz2DBackend, uint8_t* aBuffer,
|
|
|
|
size_t aBufferSize)
|
2015-12-16 21:50:58 +03:00
|
|
|
: BufferTextureData(aDesc, aMoz2DBackend),
|
2015-10-15 18:53:33 +03:00
|
|
|
mBuffer(aBuffer),
|
|
|
|
mBufferSize(aBufferSize) {
|
|
|
|
MOZ_ASSERT(aBuffer);
|
|
|
|
MOZ_ASSERT(aBufferSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual uint8_t* GetBuffer() override { return mBuffer; }
|
|
|
|
|
|
|
|
virtual size_t GetBufferSize() override { return mBufferSize; }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
uint8_t* mBuffer;
|
|
|
|
size_t mBufferSize;
|
|
|
|
};
|
|
|
|
|
|
|
|
class ShmemTextureData : public BufferTextureData {
|
|
|
|
public:
|
|
|
|
static ShmemTextureData* Create(gfx::IntSize aSize,
|
|
|
|
gfx::SurfaceFormat aFormat,
|
2016-08-23 05:30:14 +03:00
|
|
|
gfx::BackendType aMoz2DBackend,
|
|
|
|
LayersBackend aLayersBackend,
|
|
|
|
TextureFlags aFlags,
|
2015-10-15 18:53:33 +03:00
|
|
|
TextureAllocationFlags aAllocFlags,
|
2019-12-24 10:37:02 +03:00
|
|
|
LayersIPCChannel* aAllocator);
|
2015-10-15 18:53:33 +03:00
|
|
|
|
|
|
|
virtual TextureData* CreateSimilar(
|
2016-09-27 06:22:20 +03:00
|
|
|
LayersIPCChannel* aAllocator, LayersBackend aLayersBackend,
|
2015-10-15 18:53:33 +03:00
|
|
|
TextureFlags aFlags = TextureFlags::DEFAULT,
|
|
|
|
TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override;
|
|
|
|
|
|
|
|
virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;
|
|
|
|
|
2016-09-27 06:22:20 +03:00
|
|
|
virtual void Deallocate(LayersIPCChannel* aAllocator) override;
|
2015-10-15 18:53:33 +03:00
|
|
|
|
2015-12-16 21:50:58 +03:00
|
|
|
ShmemTextureData(const BufferDescriptor& aDesc,
|
2015-10-15 18:53:33 +03:00
|
|
|
gfx::BackendType aMoz2DBackend, mozilla::ipc::Shmem aShmem)
|
2015-12-16 21:50:58 +03:00
|
|
|
: BufferTextureData(aDesc, aMoz2DBackend), mShmem(aShmem) {
|
2015-10-15 18:53:33 +03:00
|
|
|
MOZ_ASSERT(mShmem.Size<uint8_t>());
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual uint8_t* GetBuffer() override { return mShmem.get<uint8_t>(); }
|
|
|
|
|
|
|
|
virtual size_t GetBufferSize() override { return mShmem.Size<uint8_t>(); }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
mozilla::ipc::Shmem mShmem;
|
|
|
|
};
|
|
|
|
|
2016-02-25 16:15:52 +03:00
|
|
|
static bool UsingX11Compositor() {
|
|
|
|
#ifdef MOZ_WIDGET_GTK
|
2016-08-04 21:33:44 +03:00
|
|
|
return gfx::gfxVars::UseXRender();
|
2016-02-25 16:15:52 +03:00
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-07-09 04:59:59 +03:00
|
|
|
bool ComputeHasIntermediateBuffer(gfx::SurfaceFormat aFormat,
|
2018-05-03 04:20:25 +03:00
|
|
|
LayersBackend aLayersBackend,
|
|
|
|
bool aSupportsTextureDirectMapping) {
|
|
|
|
if (aSupportsTextureDirectMapping) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-02-25 16:15:52 +03:00
|
|
|
return aLayersBackend != LayersBackend::LAYERS_BASIC ||
|
2016-07-09 04:59:59 +03:00
|
|
|
UsingX11Compositor() || aFormat == gfx::SurfaceFormat::UNKNOWN;
|
2016-02-25 16:15:52 +03:00
|
|
|
}
|
|
|
|
|
2019-12-24 10:37:02 +03:00
|
|
|
BufferTextureData* BufferTextureData::Create(gfx::IntSize aSize,
|
|
|
|
gfx::SurfaceFormat aFormat,
|
|
|
|
gfx::BackendType aMoz2DBackend,
|
|
|
|
LayersBackend aLayersBackend,
|
|
|
|
TextureFlags aFlags,
|
|
|
|
TextureAllocationFlags aAllocFlags,
|
|
|
|
LayersIPCChannel* aAllocator) {
|
|
|
|
if (!aAllocator || aAllocator->IsSameProcess()) {
|
2016-08-23 05:30:14 +03:00
|
|
|
return MemoryTextureData::Create(aSize, aFormat, aMoz2DBackend,
|
|
|
|
aLayersBackend, aFlags, aAllocFlags,
|
2016-02-25 16:15:52 +03:00
|
|
|
aAllocator);
|
2016-09-27 06:22:20 +03:00
|
|
|
} else {
|
2016-08-23 05:30:14 +03:00
|
|
|
return ShmemTextureData::Create(aSize, aFormat, aMoz2DBackend,
|
|
|
|
aLayersBackend, aFlags, aAllocFlags,
|
2016-02-25 16:15:52 +03:00
|
|
|
aAllocator);
|
2015-10-15 18:53:33 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-27 06:22:20 +03:00
|
|
|
BufferTextureData* BufferTextureData::CreateInternal(
|
2015-12-16 21:50:58 +03:00
|
|
|
LayersIPCChannel* aAllocator, const BufferDescriptor& aDesc,
|
|
|
|
gfx::BackendType aMoz2DBackend, int32_t aBufferSize,
|
|
|
|
TextureFlags aTextureFlags) {
|
2015-10-15 18:53:33 +03:00
|
|
|
if (!aAllocator || aAllocator->IsSameProcess()) {
|
2015-12-16 21:50:58 +03:00
|
|
|
uint8_t* buffer = new (fallible) uint8_t[aBufferSize];
|
2015-10-15 18:53:33 +03:00
|
|
|
if (!buffer) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2016-01-06 05:26:29 +03:00
|
|
|
GfxMemoryImageReporter::DidAlloc(buffer);
|
|
|
|
|
2015-12-16 21:50:58 +03:00
|
|
|
return new MemoryTextureData(aDesc, aMoz2DBackend, buffer, aBufferSize);
|
2016-09-27 06:22:20 +03:00
|
|
|
} else {
|
2015-10-15 18:53:33 +03:00
|
|
|
ipc::Shmem shm;
|
2016-09-27 06:22:20 +03:00
|
|
|
if (!aAllocator->AllocUnsafeShmem(aBufferSize, OptimalShmemType(), &shm)) {
|
2015-10-15 18:53:33 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2015-12-16 21:50:58 +03:00
|
|
|
return new ShmemTextureData(aDesc, aMoz2DBackend, shm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-27 06:22:20 +03:00
|
|
|
BufferTextureData* BufferTextureData::CreateForYCbCr(
|
|
|
|
KnowsCompositor* aAllocator, gfx::IntSize aYSize, uint32_t aYStride,
|
2015-10-15 18:53:33 +03:00
|
|
|
gfx::IntSize aCbCrSize, uint32_t aCbCrStride, StereoMode aStereoMode,
|
2019-04-11 15:41:33 +03:00
|
|
|
gfx::ColorDepth aColorDepth, gfx::YUVColorSpace aYUVColorSpace,
|
2019-07-26 11:45:31 +03:00
|
|
|
gfx::ColorRange aColorRange, TextureFlags aTextureFlags) {
|
2017-09-29 17:37:56 +03:00
|
|
|
uint32_t bufSize = ImageDataSerializer::ComputeYCbCrBufferSize(
|
|
|
|
aYSize, aYStride, aCbCrSize, aCbCrStride);
|
2015-12-16 21:50:58 +03:00
|
|
|
if (bufSize == 0) {
|
2015-10-15 18:53:33 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2015-12-16 21:50:58 +03:00
|
|
|
uint32_t yOffset;
|
|
|
|
uint32_t cbOffset;
|
|
|
|
uint32_t crOffset;
|
2017-09-29 17:37:56 +03:00
|
|
|
ImageDataSerializer::ComputeYCbCrOffsets(aYStride, aYSize.height, aCbCrStride,
|
|
|
|
aCbCrSize.height, yOffset, cbOffset,
|
|
|
|
crOffset);
|
|
|
|
|
2018-07-23 06:27:48 +03:00
|
|
|
bool supportsTextureDirectMapping =
|
|
|
|
aAllocator->SupportsTextureDirectMapping() &&
|
|
|
|
aAllocator->GetMaxTextureSize() >
|
|
|
|
std::max(aYSize.width,
|
|
|
|
std::max(aYSize.height,
|
|
|
|
std::max(aCbCrSize.width, aCbCrSize.height)));
|
|
|
|
|
2017-09-29 17:37:56 +03:00
|
|
|
bool hasIntermediateBuffer =
|
|
|
|
aAllocator
|
|
|
|
? ComputeHasIntermediateBuffer(gfx::SurfaceFormat::YUV,
|
2018-05-03 04:20:25 +03:00
|
|
|
aAllocator->GetCompositorBackendType(),
|
2018-07-23 06:27:48 +03:00
|
|
|
supportsTextureDirectMapping)
|
2017-09-29 17:37:56 +03:00
|
|
|
: true;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2019-07-26 11:45:31 +03:00
|
|
|
YCbCrDescriptor descriptor =
|
|
|
|
YCbCrDescriptor(aYSize, aYStride, aCbCrSize, aCbCrStride, yOffset,
|
|
|
|
cbOffset, crOffset, aStereoMode, aColorDepth,
|
|
|
|
aYUVColorSpace, aColorRange, hasIntermediateBuffer);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2017-09-29 17:37:56 +03:00
|
|
|
return CreateInternal(
|
|
|
|
aAllocator ? aAllocator->GetTextureForwarder() : nullptr, descriptor,
|
|
|
|
gfx::BackendType::NONE, bufSize, aTextureFlags);
|
2015-12-16 21:50:58 +03:00
|
|
|
}
|
|
|
|
|
2016-04-22 19:05:26 +03:00
|
|
|
void BufferTextureData::FillInfo(TextureData::Info& aInfo) const {
|
|
|
|
aInfo.size = GetSize();
|
|
|
|
aInfo.format = GetFormat();
|
|
|
|
aInfo.hasSynchronization = false;
|
|
|
|
aInfo.canExposeMappedData = true;
|
2015-12-16 21:50:58 +03:00
|
|
|
|
2016-02-25 16:15:52 +03:00
|
|
|
if (mDescriptor.type() == BufferDescriptor::TYCbCrDescriptor) {
|
2016-07-09 04:59:59 +03:00
|
|
|
aInfo.hasIntermediateBuffer =
|
|
|
|
mDescriptor.get_YCbCrDescriptor().hasIntermediateBuffer();
|
2016-04-22 19:05:26 +03:00
|
|
|
} else {
|
|
|
|
aInfo.hasIntermediateBuffer =
|
|
|
|
mDescriptor.get_RGBDescriptor().hasIntermediateBuffer();
|
2016-02-25 16:15:52 +03:00
|
|
|
}
|
|
|
|
|
2016-04-22 19:05:26 +03:00
|
|
|
switch (aInfo.format) {
|
2015-10-15 18:53:33 +03:00
|
|
|
case gfx::SurfaceFormat::YUV:
|
|
|
|
case gfx::SurfaceFormat::UNKNOWN:
|
2016-04-22 19:05:26 +03:00
|
|
|
aInfo.supportsMoz2D = false;
|
|
|
|
break;
|
2015-10-15 18:53:33 +03:00
|
|
|
default:
|
2016-04-22 19:05:26 +03:00
|
|
|
aInfo.supportsMoz2D = true;
|
2015-10-15 18:53:33 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-22 19:05:26 +03:00
|
|
|
gfx::IntSize BufferTextureData::GetSize() const {
|
|
|
|
return ImageDataSerializer::SizeFromBufferDescriptor(mDescriptor);
|
|
|
|
}
|
|
|
|
|
2016-06-30 05:12:31 +03:00
|
|
|
Maybe<gfx::IntSize> BufferTextureData::GetCbCrSize() const {
|
|
|
|
return ImageDataSerializer::CbCrSizeFromBufferDescriptor(mDescriptor);
|
|
|
|
}
|
|
|
|
|
2019-04-11 15:41:33 +03:00
|
|
|
Maybe<gfx::YUVColorSpace> BufferTextureData::GetYUVColorSpace() const {
|
2016-10-12 05:46:28 +03:00
|
|
|
return ImageDataSerializer::YUVColorSpaceFromBufferDescriptor(mDescriptor);
|
|
|
|
}
|
|
|
|
|
2018-09-25 23:44:55 +03:00
|
|
|
Maybe<gfx::ColorDepth> BufferTextureData::GetColorDepth() const {
|
|
|
|
return ImageDataSerializer::ColorDepthFromBufferDescriptor(mDescriptor);
|
2017-09-29 17:37:56 +03:00
|
|
|
}
|
|
|
|
|
2016-06-30 05:12:31 +03:00
|
|
|
Maybe<StereoMode> BufferTextureData::GetStereoMode() const {
|
|
|
|
return ImageDataSerializer::StereoModeFromBufferDescriptor(mDescriptor);
|
|
|
|
}
|
|
|
|
|
2016-04-22 19:05:26 +03:00
|
|
|
gfx::SurfaceFormat BufferTextureData::GetFormat() const {
|
|
|
|
return ImageDataSerializer::FormatFromBufferDescriptor(mDescriptor);
|
|
|
|
}
|
|
|
|
|
2015-10-15 18:53:33 +03:00
|
|
|
already_AddRefed<gfx::DrawTarget> BufferTextureData::BorrowDrawTarget() {
|
2015-12-16 21:50:58 +03:00
|
|
|
if (mDescriptor.type() != BufferDescriptor::TRGBDescriptor) {
|
2015-10-15 18:53:33 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2015-12-16 21:50:58 +03:00
|
|
|
const RGBDescriptor& rgb = mDescriptor.get_RGBDescriptor();
|
|
|
|
|
|
|
|
uint32_t stride = ImageDataSerializer::GetRGBStride(rgb);
|
2018-11-14 19:16:01 +03:00
|
|
|
RefPtr<gfx::DrawTarget> dt;
|
2016-11-29 23:46:49 +03:00
|
|
|
if (gfx::Factory::DoesBackendSupportDataDrawtarget(mMoz2DBackend)) {
|
2018-11-14 19:16:01 +03:00
|
|
|
dt = gfx::Factory::CreateDrawTargetForData(
|
|
|
|
mMoz2DBackend, GetBuffer(), rgb.size(), stride, rgb.format(), true);
|
|
|
|
}
|
|
|
|
if (!dt) {
|
2016-11-29 23:46:49 +03:00
|
|
|
// Fall back to supported platform backend. Note that mMoz2DBackend
|
|
|
|
// does not match the draw target type.
|
2018-11-14 19:16:01 +03:00
|
|
|
dt = gfxPlatform::CreateDrawTargetForData(GetBuffer(), rgb.size(), stride,
|
|
|
|
rgb.format(), true);
|
2015-12-16 21:50:58 +03:00
|
|
|
}
|
|
|
|
|
2018-11-14 19:16:01 +03:00
|
|
|
if (!dt) {
|
2015-10-15 18:53:33 +03:00
|
|
|
gfxCriticalNote << "BorrowDrawTarget failure, original backend "
|
|
|
|
<< (int)mMoz2DBackend;
|
|
|
|
}
|
|
|
|
|
|
|
|
return dt.forget();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BufferTextureData::BorrowMappedData(MappedTextureData& aData) {
|
2015-12-16 21:50:58 +03:00
|
|
|
if (GetFormat() == gfx::SurfaceFormat::YUV) {
|
2015-10-15 18:53:33 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-12-16 21:50:58 +03:00
|
|
|
gfx::IntSize size = GetSize();
|
2015-10-15 18:53:33 +03:00
|
|
|
|
2015-12-16 21:50:58 +03:00
|
|
|
aData.data = GetBuffer();
|
|
|
|
aData.size = size;
|
|
|
|
aData.format = GetFormat();
|
|
|
|
aData.stride =
|
|
|
|
ImageDataSerializer::ComputeRGBStride(aData.format, size.width);
|
2015-10-15 18:53:33 +03:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BufferTextureData::BorrowMappedYCbCrData(MappedYCbCrTextureData& aMap) {
|
2015-12-16 21:50:58 +03:00
|
|
|
if (mDescriptor.type() != BufferDescriptor::TYCbCrDescriptor) {
|
2015-10-15 18:53:33 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-12-16 21:50:58 +03:00
|
|
|
const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
|
|
|
|
|
|
|
|
uint8_t* data = GetBuffer();
|
|
|
|
auto ySize = desc.ySize();
|
|
|
|
auto cbCrSize = desc.cbCrSize();
|
2015-10-15 18:53:33 +03:00
|
|
|
|
2015-12-16 21:50:58 +03:00
|
|
|
aMap.stereoMode = desc.stereoMode();
|
|
|
|
aMap.metadata = nullptr;
|
2018-09-25 23:44:55 +03:00
|
|
|
uint32_t bytesPerPixel =
|
|
|
|
BytesPerPixel(SurfaceFormatForColorDepth(desc.colorDepth()));
|
2015-10-15 18:53:33 +03:00
|
|
|
|
2015-12-16 21:50:58 +03:00
|
|
|
aMap.y.data = data + desc.yOffset();
|
|
|
|
aMap.y.size = ySize;
|
2017-09-29 17:37:56 +03:00
|
|
|
aMap.y.stride = desc.yStride();
|
2015-10-15 18:53:33 +03:00
|
|
|
aMap.y.skip = 0;
|
2017-11-28 17:53:54 +03:00
|
|
|
aMap.y.bytesPerPixel = bytesPerPixel;
|
2015-10-15 18:53:33 +03:00
|
|
|
|
2015-12-16 21:50:58 +03:00
|
|
|
aMap.cb.data = data + desc.cbOffset();
|
|
|
|
aMap.cb.size = cbCrSize;
|
2017-09-29 17:37:56 +03:00
|
|
|
aMap.cb.stride = desc.cbCrStride();
|
2015-10-15 18:53:33 +03:00
|
|
|
aMap.cb.skip = 0;
|
2017-11-28 17:53:54 +03:00
|
|
|
aMap.cb.bytesPerPixel = bytesPerPixel;
|
2015-10-15 18:53:33 +03:00
|
|
|
|
2015-12-16 21:50:58 +03:00
|
|
|
aMap.cr.data = data + desc.crOffset();
|
|
|
|
aMap.cr.size = cbCrSize;
|
2017-09-29 17:37:56 +03:00
|
|
|
aMap.cr.stride = desc.cbCrStride();
|
2015-10-15 18:53:33 +03:00
|
|
|
aMap.cr.skip = 0;
|
2017-11-28 17:53:54 +03:00
|
|
|
aMap.cr.bytesPerPixel = bytesPerPixel;
|
2015-10-15 18:53:33 +03:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BufferTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface) {
|
2015-12-16 21:50:58 +03:00
|
|
|
if (mDescriptor.type() != BufferDescriptor::TRGBDescriptor) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const RGBDescriptor& rgb = mDescriptor.get_RGBDescriptor();
|
2015-10-15 18:53:33 +03:00
|
|
|
|
2015-12-16 21:50:58 +03:00
|
|
|
uint32_t stride = ImageDataSerializer::GetRGBStride(rgb);
|
|
|
|
RefPtr<gfx::DataSourceSurface> surface =
|
|
|
|
gfx::Factory::CreateWrappingDataSourceSurface(GetBuffer(), stride,
|
|
|
|
rgb.size(), rgb.format());
|
2015-10-15 18:53:33 +03:00
|
|
|
|
|
|
|
if (!surface) {
|
|
|
|
gfxCriticalError() << "Failed to get serializer as surface!";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
RefPtr<gfx::DataSourceSurface> srcSurf = aSurface->GetDataSurface();
|
|
|
|
|
|
|
|
if (!srcSurf) {
|
2015-12-29 22:03:58 +03:00
|
|
|
gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface (BT).";
|
2015-10-15 18:53:33 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (surface->GetSize() != srcSurf->GetSize() ||
|
|
|
|
surface->GetFormat() != srcSurf->GetFormat()) {
|
2015-12-29 22:03:58 +03:00
|
|
|
gfxCriticalError() << "Attempt to update texture client from a surface "
|
|
|
|
"with a different size or format (BT)! This: "
|
|
|
|
<< surface->GetSize() << " " << surface->GetFormat()
|
|
|
|
<< " Other: " << aSurface->GetSize() << " "
|
|
|
|
<< aSurface->GetFormat();
|
2015-10-15 18:53:33 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
gfx::DataSourceSurface::MappedSurface sourceMap;
|
|
|
|
gfx::DataSourceSurface::MappedSurface destMap;
|
|
|
|
if (!srcSurf->Map(gfx::DataSourceSurface::READ, &sourceMap)) {
|
2015-12-29 22:03:58 +03:00
|
|
|
gfxCriticalError()
|
|
|
|
<< "Failed to map source surface for UpdateFromSurface (BT).";
|
2015-10-15 18:53:33 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!surface->Map(gfx::DataSourceSurface::WRITE, &destMap)) {
|
|
|
|
srcSurf->Unmap();
|
|
|
|
gfxCriticalError()
|
|
|
|
<< "Failed to map destination surface for UpdateFromSurface.";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int y = 0; y < srcSurf->GetSize().height; y++) {
|
|
|
|
memcpy(destMap.mData + destMap.mStride * y,
|
|
|
|
sourceMap.mData + sourceMap.mStride * y,
|
|
|
|
srcSurf->GetSize().width * BytesPerPixel(srcSurf->GetFormat()));
|
|
|
|
}
|
|
|
|
|
|
|
|
srcSurf->Unmap();
|
|
|
|
surface->Unmap();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-09-25 15:18:58 +03:00
|
|
|
void BufferTextureData::SetDescriptor(BufferDescriptor&& aDescriptor) {
|
2015-12-16 21:50:58 +03:00
|
|
|
MOZ_ASSERT(mDescriptor.type() == BufferDescriptor::TYCbCrDescriptor);
|
|
|
|
MOZ_ASSERT(mDescriptor.get_YCbCrDescriptor().ySize() == gfx::IntSize());
|
2018-09-25 15:18:58 +03:00
|
|
|
mDescriptor = std::move(aDescriptor);
|
2015-12-16 21:50:58 +03:00
|
|
|
}
|
|
|
|
|
2015-10-15 18:53:33 +03:00
|
|
|
bool MemoryTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) {
|
|
|
|
MOZ_ASSERT(GetFormat() != gfx::SurfaceFormat::UNKNOWN);
|
|
|
|
if (GetFormat() == gfx::SurfaceFormat::UNKNOWN) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-12-16 21:50:58 +03:00
|
|
|
uintptr_t ptr = reinterpret_cast<uintptr_t>(mBuffer);
|
|
|
|
aOutDescriptor = SurfaceDescriptorBuffer(mDescriptor, MemoryOrShmem(ptr));
|
|
|
|
|
2015-10-15 18:53:33 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-03-12 07:24:21 +03:00
|
|
|
static bool InitBuffer(uint8_t* buf, size_t bufSize, gfx::SurfaceFormat aFormat,
|
|
|
|
TextureAllocationFlags aAllocFlags, bool aAlreadyZero) {
|
2015-10-15 18:53:33 +03:00
|
|
|
if (!buf) {
|
|
|
|
gfxDebug() << "BufferTextureData: Failed to allocate " << bufSize
|
|
|
|
<< " bytes";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-02-17 18:34:37 +03:00
|
|
|
if ((aAllocFlags & ALLOC_CLEAR_BUFFER) ||
|
|
|
|
(aAllocFlags & ALLOC_CLEAR_BUFFER_BLACK)) {
|
2016-03-18 23:58:55 +03:00
|
|
|
if (aFormat == gfx::SurfaceFormat::B8G8R8X8) {
|
|
|
|
// Even though BGRX was requested, XRGB_UINT32 is what is meant,
|
|
|
|
// so use 0xFF000000 to put alpha in the right place.
|
2016-06-11 04:49:46 +03:00
|
|
|
libyuv::ARGBRect(buf, bufSize, 0, 0, bufSize / sizeof(uint32_t), 1,
|
|
|
|
0xFF000000);
|
2016-03-12 07:24:21 +03:00
|
|
|
} else if (!aAlreadyZero) {
|
2016-03-18 23:58:55 +03:00
|
|
|
memset(buf, 0, bufSize);
|
|
|
|
}
|
2015-10-15 18:53:33 +03:00
|
|
|
}
|
2016-02-17 18:34:37 +03:00
|
|
|
|
2015-10-15 18:53:33 +03:00
|
|
|
if (aAllocFlags & ALLOC_CLEAR_BUFFER_WHITE) {
|
|
|
|
memset(buf, 0xFF, bufSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
MemoryTextureData* MemoryTextureData::Create(gfx::IntSize aSize,
|
|
|
|
gfx::SurfaceFormat aFormat,
|
2016-08-23 05:30:14 +03:00
|
|
|
gfx::BackendType aMoz2DBackend,
|
|
|
|
LayersBackend aLayersBackend,
|
|
|
|
TextureFlags aFlags,
|
2015-10-15 18:53:33 +03:00
|
|
|
TextureAllocationFlags aAllocFlags,
|
2019-12-24 10:37:02 +03:00
|
|
|
LayersIPCChannel* aAllocator) {
|
2015-12-16 21:50:58 +03:00
|
|
|
// Should have used CreateForYCbCr.
|
|
|
|
MOZ_ASSERT(aFormat != gfx::SurfaceFormat::YUV);
|
|
|
|
|
2015-10-15 18:53:33 +03:00
|
|
|
if (aSize.width <= 0 || aSize.height <= 0) {
|
|
|
|
gfxDebug() << "Asking for buffer of invalid size " << aSize.width << "x"
|
|
|
|
<< aSize.height;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2015-12-16 21:50:58 +03:00
|
|
|
uint32_t bufSize = ImageDataSerializer::ComputeRGBBufferSize(aSize, aFormat);
|
2015-10-15 18:53:33 +03:00
|
|
|
if (!bufSize) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t* buf = new (fallible) uint8_t[bufSize];
|
2016-03-12 07:24:21 +03:00
|
|
|
if (!InitBuffer(buf, bufSize, aFormat, aAllocFlags, false)) {
|
2015-12-16 21:50:58 +03:00
|
|
|
return nullptr;
|
2015-10-15 18:53:33 +03:00
|
|
|
}
|
|
|
|
|
2018-05-03 04:20:25 +03:00
|
|
|
bool hasIntermediateBuffer = ComputeHasIntermediateBuffer(
|
|
|
|
aFormat, aLayersBackend, aAllocFlags & ALLOC_ALLOW_DIRECT_MAPPING);
|
2016-02-25 16:15:52 +03:00
|
|
|
|
2015-12-16 21:50:58 +03:00
|
|
|
GfxMemoryImageReporter::DidAlloc(buf);
|
|
|
|
|
2016-02-25 16:15:58 +03:00
|
|
|
BufferDescriptor descriptor =
|
|
|
|
RGBDescriptor(aSize, aFormat, hasIntermediateBuffer);
|
2015-12-16 21:50:58 +03:00
|
|
|
|
|
|
|
return new MemoryTextureData(descriptor, aMoz2DBackend, buf, bufSize);
|
2015-10-15 18:53:33 +03:00
|
|
|
}
|
|
|
|
|
2016-09-27 06:22:20 +03:00
|
|
|
void MemoryTextureData::Deallocate(LayersIPCChannel*) {
|
2015-10-15 18:53:33 +03:00
|
|
|
MOZ_ASSERT(mBuffer);
|
|
|
|
GfxMemoryImageReporter::WillFree(mBuffer);
|
|
|
|
delete[] mBuffer;
|
|
|
|
mBuffer = nullptr;
|
|
|
|
}
|
|
|
|
|
2016-09-27 06:22:20 +03:00
|
|
|
TextureData* MemoryTextureData::CreateSimilar(
|
|
|
|
LayersIPCChannel* aAllocator, LayersBackend aLayersBackend,
|
2015-10-15 18:53:33 +03:00
|
|
|
TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const {
|
2015-12-16 21:50:58 +03:00
|
|
|
return MemoryTextureData::Create(GetSize(), GetFormat(), mMoz2DBackend,
|
2016-09-27 06:22:20 +03:00
|
|
|
aLayersBackend, aFlags, aAllocFlags,
|
|
|
|
aAllocator);
|
2015-10-15 18:53:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool ShmemTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) {
|
|
|
|
MOZ_ASSERT(GetFormat() != gfx::SurfaceFormat::UNKNOWN);
|
|
|
|
if (GetFormat() == gfx::SurfaceFormat::UNKNOWN) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-03-04 19:35:30 +03:00
|
|
|
aOutDescriptor =
|
|
|
|
SurfaceDescriptorBuffer(mDescriptor, MemoryOrShmem(std::move(mShmem)));
|
2015-10-15 18:53:33 +03:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
ShmemTextureData* ShmemTextureData::Create(gfx::IntSize aSize,
|
|
|
|
gfx::SurfaceFormat aFormat,
|
2016-08-23 05:30:14 +03:00
|
|
|
gfx::BackendType aMoz2DBackend,
|
|
|
|
LayersBackend aLayersBackend,
|
|
|
|
TextureFlags aFlags,
|
2015-10-15 18:53:33 +03:00
|
|
|
TextureAllocationFlags aAllocFlags,
|
2019-12-24 10:37:02 +03:00
|
|
|
LayersIPCChannel* aAllocator) {
|
2015-10-15 18:53:33 +03:00
|
|
|
MOZ_ASSERT(aAllocator);
|
2015-12-16 21:50:58 +03:00
|
|
|
// Should have used CreateForYCbCr.
|
|
|
|
MOZ_ASSERT(aFormat != gfx::SurfaceFormat::YUV);
|
|
|
|
|
2016-09-27 06:22:20 +03:00
|
|
|
if (!aAllocator) {
|
2015-10-15 18:53:33 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aSize.width <= 0 || aSize.height <= 0) {
|
|
|
|
gfxDebug() << "Asking for buffer of invalid size " << aSize.width << "x"
|
|
|
|
<< aSize.height;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2015-12-16 21:50:58 +03:00
|
|
|
uint32_t bufSize = ImageDataSerializer::ComputeRGBBufferSize(aSize, aFormat);
|
2015-10-15 18:53:33 +03:00
|
|
|
if (!bufSize) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
mozilla::ipc::Shmem shm;
|
2016-09-27 06:22:20 +03:00
|
|
|
if (!aAllocator->AllocUnsafeShmem(bufSize, OptimalShmemType(), &shm)) {
|
2015-10-15 18:53:33 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t* buf = shm.get<uint8_t>();
|
2016-03-12 07:24:21 +03:00
|
|
|
if (!InitBuffer(buf, bufSize, aFormat, aAllocFlags, true)) {
|
2015-12-16 21:50:58 +03:00
|
|
|
return nullptr;
|
2015-10-15 18:53:33 +03:00
|
|
|
}
|
|
|
|
|
2018-05-03 04:20:25 +03:00
|
|
|
bool hasIntermediateBuffer = ComputeHasIntermediateBuffer(
|
|
|
|
aFormat, aLayersBackend, aAllocFlags & ALLOC_ALLOW_DIRECT_MAPPING);
|
2016-02-25 16:15:52 +03:00
|
|
|
|
2016-02-25 16:15:58 +03:00
|
|
|
BufferDescriptor descriptor =
|
|
|
|
RGBDescriptor(aSize, aFormat, hasIntermediateBuffer);
|
2015-12-16 21:50:58 +03:00
|
|
|
|
|
|
|
return new ShmemTextureData(descriptor, aMoz2DBackend, shm);
|
2015-10-15 18:53:33 +03:00
|
|
|
}
|
|
|
|
|
2016-09-27 06:22:20 +03:00
|
|
|
TextureData* ShmemTextureData::CreateSimilar(
|
|
|
|
LayersIPCChannel* aAllocator, LayersBackend aLayersBackend,
|
2015-10-15 18:53:33 +03:00
|
|
|
TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const {
|
2015-12-16 21:50:58 +03:00
|
|
|
return ShmemTextureData::Create(GetSize(), GetFormat(), mMoz2DBackend,
|
2016-09-27 06:22:20 +03:00
|
|
|
aLayersBackend, aFlags, aAllocFlags,
|
|
|
|
aAllocator);
|
2015-10-15 18:53:33 +03:00
|
|
|
}
|
|
|
|
|
2016-09-27 06:22:20 +03:00
|
|
|
void ShmemTextureData::Deallocate(LayersIPCChannel* aAllocator) {
|
|
|
|
aAllocator->DeallocShmem(mShmem);
|
2015-10-15 18:53:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace layers
|
|
|
|
} // namespace mozilla
|