Bug 1063733 - Optimize DataSourceSurface allocation, r=bas,seth

This commit is contained in:
Michael Wu 2014-09-10 17:54:16 -04:00
parent 60ddfcde08
commit e58cfe332e
11 changed files with 41 additions and 34 deletions

View File

@ -416,12 +416,11 @@ ImageEncoder::ExtractDataInternal(const nsAString& aType,
RefPtr<DataSourceSurface> emptyCanvas =
Factory::CreateDataSourceSurfaceWithStride(IntSize(aSize.width, aSize.height),
SurfaceFormat::B8G8R8A8,
4 * aSize.width);
4 * aSize.width, true);
if (NS_WARN_IF(!emptyCanvas)) {
return NS_ERROR_INVALID_ARG;
}
ClearDataSourceSurface(emptyCanvas);
DataSourceSurface::MappedSurface map;
if (!emptyCanvas->Map(DataSourceSurface::MapType::WRITE, &map)) {
return NS_ERROR_INVALID_ARG;

View File

@ -1117,20 +1117,20 @@ public:
* This creates a simple data source surface for a certain size. It allocates
* new memory for the surface. This memory is freed when the surface is
* destroyed. The caller is responsible for handing the case where nullptr
* is returned.
* is returned. The surface is not zeroed unless requested.
*/
static TemporaryRef<DataSourceSurface>
CreateDataSourceSurface(const IntSize &aSize, SurfaceFormat aFormat);
CreateDataSourceSurface(const IntSize &aSize, SurfaceFormat aFormat, bool aZero = false);
/**
* This creates a simple data source surface for a certain size with a
* specific stride, which must be large enough to fit all pixels.
* It allocates new memory for the surface. This memory is freed when
* the surface is destroyed. The caller is responsible for handling the case
* where nullptr is returned.
* where nullptr is returned. The surface is not zeroed unless requested.
*/
static TemporaryRef<DataSourceSurface>
CreateDataSourceSurfaceWithStride(const IntSize &aSize, SurfaceFormat aFormat, int32_t aStride);
CreateDataSourceSurfaceWithStride(const IntSize &aSize, SurfaceFormat aFormat, int32_t aStride, bool aZero = false);
/**
* This creates a simple data source surface for some existing data. It will

View File

@ -48,6 +48,8 @@ SurfaceToPackedBGR(DataSourceSurface *aSurface);
/**
* Clears all the bytes in a DataSourceSurface's data array to zero (so to
* transparent black for SurfaceFormat::B8G8R8A8, for example).
* Note that DataSourceSurfaces can be initialized to zero, which is
* more efficient than zeroing the surface after initialization.
*/
void
ClearDataSourceSurface(DataSourceSurface *aSurface);

View File

@ -1358,9 +1358,8 @@ DrawTargetCG::Init(BackendType aType,
}
static_assert(sizeof(decltype(mData[0])) == 1,
"mData.Realloc() takes an object count, so its objects must be 1-byte sized if we use bufLen");
mData.Realloc(/* actually an object count */ bufLen);
mData.Realloc(/* actually an object count */ bufLen, true);
aData = static_cast<unsigned char*>(mData);
memset(aData, 0, bufLen);
}
mSize = aSize;

View File

@ -700,7 +700,8 @@ Factory::CreateWrappingDataSourceSurface(uint8_t *aData, int32_t aStride,
TemporaryRef<DataSourceSurface>
Factory::CreateDataSourceSurface(const IntSize &aSize,
SurfaceFormat aFormat)
SurfaceFormat aFormat,
bool aZero)
{
if (!CheckSurfaceSize(aSize)) {
gfxWarning() << "CreateDataSourceSurface failed with bad size";
@ -708,7 +709,7 @@ Factory::CreateDataSourceSurface(const IntSize &aSize,
}
RefPtr<SourceSurfaceAlignedRawData> newSurf = new SourceSurfaceAlignedRawData();
if (newSurf->Init(aSize, aFormat)) {
if (newSurf->Init(aSize, aFormat, aZero)) {
return newSurf.forget();
}
@ -719,7 +720,8 @@ Factory::CreateDataSourceSurface(const IntSize &aSize,
TemporaryRef<DataSourceSurface>
Factory::CreateDataSourceSurfaceWithStride(const IntSize &aSize,
SurfaceFormat aFormat,
int32_t aStride)
int32_t aStride,
bool aZero)
{
if (aStride < aSize.width * BytesPerPixel(aFormat)) {
gfxWarning() << "CreateDataSourceSurfaceWithStride failed with bad stride";
@ -727,7 +729,7 @@ Factory::CreateDataSourceSurfaceWithStride(const IntSize &aSize,
}
RefPtr<SourceSurfaceAlignedRawData> newSurf = new SourceSurfaceAlignedRawData();
if (newSurf->InitWithStride(aSize, aFormat, aStride)) {
if (newSurf->InitWithStride(aSize, aFormat, aStride, aZero)) {
return newSurf.forget();
}

View File

@ -492,16 +492,13 @@ GetDataSurfaceInRect(SourceSurface *aSurface,
IntRect intersectInDestSpace = intersect - aDestRect.TopLeft();
SurfaceFormat format = aSurface ? aSurface->GetFormat() : SurfaceFormat(SurfaceFormat::B8G8R8A8);
bool clear = aEdgeMode == EDGE_MODE_NONE && !aSurfaceRect.Contains(aDestRect);
RefPtr<DataSourceSurface> target =
Factory::CreateDataSourceSurface(aDestRect.Size(), format);
Factory::CreateDataSourceSurface(aDestRect.Size(), format, clear);
if (MOZ2D_WARN_IF(!target)) {
return nullptr;
}
if (aEdgeMode == EDGE_MODE_NONE && !aSurfaceRect.Contains(aDestRect)) {
ClearDataSourceSurface(target);
}
if (!aSurface) {
return target.forget();
}
@ -2371,11 +2368,10 @@ FilterNodeConvolveMatrixSoftware::DoRender(const IntRect& aRect,
DebugOnlyAutoColorSamplingAccessControl accessControl(input);
RefPtr<DataSourceSurface> target =
Factory::CreateDataSourceSurface(aRect.Size(), SurfaceFormat::B8G8R8A8);
Factory::CreateDataSourceSurface(aRect.Size(), SurfaceFormat::B8G8R8A8, true);
if (MOZ2D_WARN_IF(!target)) {
return nullptr;
}
ClearDataSourceSurface(target);
IntPoint offset = aRect.TopLeft() - srcRect.TopLeft();
@ -2776,15 +2772,13 @@ FilterNodeCompositeSoftware::Render(const IntRect& aRect)
RefPtr<DataSourceSurface> start =
GetInputDataSourceSurface(IN_COMPOSITE_IN_START, aRect, NEED_COLOR_CHANNELS);
RefPtr<DataSourceSurface> dest =
Factory::CreateDataSourceSurface(aRect.Size(), SurfaceFormat::B8G8R8A8);
Factory::CreateDataSourceSurface(aRect.Size(), SurfaceFormat::B8G8R8A8, !start);
if (MOZ2D_WARN_IF(!dest)) {
return nullptr;
}
if (start) {
CopyRect(start, dest, aRect - aRect.TopLeft(), IntPoint());
} else {
ClearDataSourceSurface(dest);
}
for (size_t inputIndex = 1; inputIndex < NumberOfSetInputs(); inputIndex++) {

View File

@ -44,7 +44,8 @@ SourceSurfaceRawData::GuaranteePersistance()
bool
SourceSurfaceAlignedRawData::Init(const IntSize &aSize,
SurfaceFormat aFormat)
SurfaceFormat aFormat,
bool aZero)
{
mFormat = aFormat;
mStride = GetAlignedStride<16>(aSize.width * BytesPerPixel(aFormat));
@ -53,7 +54,7 @@ SourceSurfaceAlignedRawData::Init(const IntSize &aSize,
if (bufLen > 0) {
static_assert(sizeof(decltype(mArray[0])) == 1,
"mArray.Realloc() takes an object count, so its objects must be 1-byte sized if we use bufLen");
mArray.Realloc(/* actually an object count */ bufLen);
mArray.Realloc(/* actually an object count */ bufLen, aZero);
mSize = aSize;
} else {
mArray.Dealloc();
@ -66,7 +67,8 @@ SourceSurfaceAlignedRawData::Init(const IntSize &aSize,
bool
SourceSurfaceAlignedRawData::InitWithStride(const IntSize &aSize,
SurfaceFormat aFormat,
int32_t aStride)
int32_t aStride,
bool aZero)
{
mFormat = aFormat;
mStride = aStride;
@ -75,7 +77,7 @@ SourceSurfaceAlignedRawData::InitWithStride(const IntSize &aSize,
if (bufLen > 0) {
static_assert(sizeof(decltype(mArray[0])) == 1,
"mArray.Realloc() takes an object count, so its objects must be 1-byte sized if we use bufLen");
mArray.Realloc(/* actually an object count */ bufLen);
mArray.Realloc(/* actually an object count */ bufLen, aZero);
mSize = aSize;
} else {
mArray.Dealloc();

View File

@ -56,10 +56,12 @@ public:
virtual SurfaceFormat GetFormat() const { return mFormat; }
bool Init(const IntSize &aSize,
SurfaceFormat aFormat);
SurfaceFormat aFormat,
bool aZero);
bool InitWithStride(const IntSize &aSize,
SurfaceFormat aFormat,
int32_t aStride);
int32_t aStride,
bool aZero);
private:
AlignedArray<uint8_t> mArray;

View File

@ -103,11 +103,11 @@ struct AlignedArray
{
}
explicit MOZ_ALWAYS_INLINE AlignedArray(size_t aCount)
explicit MOZ_ALWAYS_INLINE AlignedArray(size_t aCount, bool aZero = false)
: mStorage(nullptr)
, mCount(0)
{
Realloc(aCount);
Realloc(aCount, aZero);
}
MOZ_ALWAYS_INLINE ~AlignedArray()
@ -138,7 +138,7 @@ struct AlignedArray
mPtr = nullptr;
}
MOZ_ALWAYS_INLINE void Realloc(size_t aCount)
MOZ_ALWAYS_INLINE void Realloc(size_t aCount, bool aZero = false)
{
delete [] mStorage;
CheckedInt32 storageByteCount =
@ -151,7 +151,11 @@ struct AlignedArray
}
// We don't create an array of T here, since we don't want ctors to be
// invoked at the wrong places if we realign below.
mStorage = new (std::nothrow) uint8_t[storageByteCount.value()];
if (aZero) {
mStorage = static_cast<uint8_t *>(calloc(1, storageByteCount.value()));
} else {
mStorage = new (std::nothrow) uint8_t[storageByteCount.value()];
}
if (!mStorage) {
mStorage = nullptr;
mPtr = nullptr;

View File

@ -863,7 +863,9 @@ RasterImage::CopyFrame(uint32_t aWhichFrame,
IntSize size(mSize.width, mSize.height);
RefPtr<DataSourceSurface> surf =
Factory::CreateDataSourceSurface(size, SurfaceFormat::B8G8R8A8);
Factory::CreateDataSourceSurface(size,
SurfaceFormat::B8G8R8A8,
/* aZero = */ true);
if (NS_WARN_IF(!surf)) {
return nullptr;
}

View File

@ -274,7 +274,8 @@ NS_IMETHODIMP imgTools::EncodeCroppedImage(imgIContainer *aContainer,
RefPtr<DataSourceSurface> dataSurface =
Factory::CreateDataSourceSurface(IntSize(aWidth, aHeight),
SurfaceFormat::B8G8R8A8);
SurfaceFormat::B8G8R8A8,
/* aZero = */ true);
if (NS_WARN_IF(!dataSurface)) {
return NS_ERROR_FAILURE;
}