michael@0: /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "ImageDataSerializer.h" michael@0: #include "gfx2DGlue.h" // for SurfaceFormatToImageFormat michael@0: #include "gfxImageSurface.h" // for gfxImageSurface michael@0: #include "gfxPoint.h" // for gfxIntSize michael@0: #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc michael@0: #include "mozilla/gfx/2D.h" // for DataSourceSurface, Factory michael@0: #include "mozilla/gfx/Tools.h" // for GetAlignedStride, etc michael@0: #include "mozilla/mozalloc.h" // for operator delete, etc michael@0: michael@0: namespace mozilla { michael@0: namespace layers { michael@0: michael@0: using namespace gfx; michael@0: michael@0: // The Data is layed out as follows: michael@0: // michael@0: // +-------------------+ -++ --+ <-- ImageDataSerializerBase::mData pointer michael@0: // | SurfaceBufferInfo | | | michael@0: // +-------------------+ --+ | offset michael@0: // | ... | | michael@0: // +-------------------+ ------+ michael@0: // | | michael@0: // | data | michael@0: // | | michael@0: // +-------------------+ michael@0: michael@0: // Structure written at the beginning of the data blob containing the image michael@0: // (as shown in the figure above). It contains the necessary informations to michael@0: // read the image in the blob. michael@0: namespace { michael@0: struct SurfaceBufferInfo michael@0: { michael@0: uint32_t width; michael@0: uint32_t height; michael@0: SurfaceFormat format; michael@0: michael@0: static uint32_t GetOffset() michael@0: { michael@0: return GetAlignedStride<16>(sizeof(SurfaceBufferInfo)); michael@0: } michael@0: }; michael@0: } // anonymous namespace michael@0: michael@0: static SurfaceBufferInfo* michael@0: GetBufferInfo(uint8_t* aData, size_t aDataSize) michael@0: { michael@0: return aDataSize >= sizeof(SurfaceBufferInfo) michael@0: ? reinterpret_cast(aData) michael@0: : nullptr; michael@0: } michael@0: michael@0: void michael@0: ImageDataSerializer::InitializeBufferInfo(IntSize aSize, michael@0: SurfaceFormat aFormat) michael@0: { michael@0: SurfaceBufferInfo* info = GetBufferInfo(mData, mDataSize); michael@0: MOZ_ASSERT(info); // OK to assert here, this method is client-side-only michael@0: info->width = aSize.width; michael@0: info->height = aSize.height; michael@0: info->format = aFormat; michael@0: Validate(); michael@0: } michael@0: michael@0: static inline uint32_t michael@0: ComputeStride(SurfaceFormat aFormat, uint32_t aWidth) michael@0: { michael@0: return GetAlignedStride<4>(BytesPerPixel(aFormat) * aWidth); michael@0: } michael@0: michael@0: uint32_t michael@0: ImageDataSerializerBase::ComputeMinBufferSize(IntSize aSize, michael@0: SurfaceFormat aFormat) michael@0: { michael@0: uint32_t bufsize = aSize.height * ComputeStride(aFormat, aSize.width); michael@0: return SurfaceBufferInfo::GetOffset() michael@0: + GetAlignedStride<16>(bufsize); michael@0: } michael@0: michael@0: void michael@0: ImageDataSerializerBase::Validate() michael@0: { michael@0: mIsValid = false; michael@0: if (!mData) { michael@0: return; michael@0: } michael@0: SurfaceBufferInfo* info = GetBufferInfo(mData, mDataSize); michael@0: if (!info) { michael@0: return; michael@0: } michael@0: size_t requiredSize = michael@0: ComputeMinBufferSize(IntSize(info->width, info->height), info->format); michael@0: mIsValid = requiredSize <= mDataSize; michael@0: } michael@0: michael@0: uint8_t* michael@0: ImageDataSerializerBase::GetData() michael@0: { michael@0: MOZ_ASSERT(IsValid()); michael@0: return mData + SurfaceBufferInfo::GetOffset(); michael@0: } michael@0: michael@0: uint32_t michael@0: ImageDataSerializerBase::GetStride() const michael@0: { michael@0: MOZ_ASSERT(IsValid()); michael@0: SurfaceBufferInfo* info = GetBufferInfo(mData, mDataSize); michael@0: return ComputeStride(GetFormat(), info->width); michael@0: } michael@0: michael@0: IntSize michael@0: ImageDataSerializerBase::GetSize() const michael@0: { michael@0: MOZ_ASSERT(IsValid()); michael@0: SurfaceBufferInfo* info = GetBufferInfo(mData, mDataSize); michael@0: return IntSize(info->width, info->height); michael@0: } michael@0: michael@0: SurfaceFormat michael@0: ImageDataSerializerBase::GetFormat() const michael@0: { michael@0: MOZ_ASSERT(IsValid()); michael@0: return GetBufferInfo(mData, mDataSize)->format; michael@0: } michael@0: michael@0: TemporaryRef michael@0: ImageDataSerializerBase::GetAsThebesSurface() michael@0: { michael@0: MOZ_ASSERT(IsValid()); michael@0: IntSize size = GetSize(); michael@0: return new gfxImageSurface(GetData(), michael@0: gfxIntSize(size.width, size.height), michael@0: GetStride(), michael@0: SurfaceFormatToImageFormat(GetFormat())); michael@0: } michael@0: michael@0: TemporaryRef michael@0: ImageDataSerializerBase::GetAsDrawTarget(gfx::BackendType aBackend) michael@0: { michael@0: MOZ_ASSERT(IsValid()); michael@0: return gfx::Factory::CreateDrawTargetForData(aBackend, michael@0: GetData(), GetSize(), michael@0: GetStride(), GetFormat()); michael@0: } michael@0: michael@0: TemporaryRef michael@0: ImageDataSerializerBase::GetAsSurface() michael@0: { michael@0: MOZ_ASSERT(IsValid()); michael@0: return Factory::CreateWrappingDataSourceSurface(GetData(), michael@0: GetStride(), michael@0: GetSize(), michael@0: GetFormat()); michael@0: } michael@0: michael@0: } // namespace layers michael@0: } // namespace mozilla