gecko/gfx/2d/SourceSurfaceSkia.cpp
Kevin Simons e00cc665ff Bug 944412 - Fix an issue with the stride in SourceSurfaceSkia::InitFromData. r=gal
After calling SkBitmap::copyTo, the InitFromData method assumed
that the stride of the destination SkBitmap was now the same as the
stride of the source bitmap. This was, however, not the case. Now
the stride is read back out of the destination bitmap.

This was causing a crash due to memory corruption for FORMAT_B8G8R8X8
surfaces.
2013-12-02 11:03:13 -05:00

126 lines
2.7 KiB
C++

/* -*- 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 "Logging.h"
#include "SourceSurfaceSkia.h"
#include "skia/SkBitmap.h"
#include "skia/SkDevice.h"
#include "HelpersSkia.h"
#include "DrawTargetSkia.h"
#include "DataSurfaceHelpers.h"
namespace mozilla {
namespace gfx {
SourceSurfaceSkia::SourceSurfaceSkia()
: mDrawTarget(nullptr), mLocked(false)
{
}
SourceSurfaceSkia::~SourceSurfaceSkia()
{
MaybeUnlock();
if (mDrawTarget) {
mDrawTarget->SnapshotDestroyed();
mDrawTarget = nullptr;
}
}
IntSize
SourceSurfaceSkia::GetSize() const
{
return mSize;
}
SurfaceFormat
SourceSurfaceSkia::GetFormat() const
{
return mFormat;
}
bool
SourceSurfaceSkia::InitFromCanvas(SkCanvas* aCanvas,
SurfaceFormat aFormat,
DrawTargetSkia* aOwner)
{
SkISize size = aCanvas->getDeviceSize();
mBitmap = (SkBitmap)aCanvas->getDevice()->accessBitmap(false);
mFormat = aFormat;
mSize = IntSize(size.fWidth, size.fHeight);
mStride = mBitmap.rowBytes();
mDrawTarget = aOwner;
return true;
}
bool
SourceSurfaceSkia::InitFromData(unsigned char* aData,
const IntSize &aSize,
int32_t aStride,
SurfaceFormat aFormat)
{
SkBitmap temp;
temp.setConfig(GfxFormatToSkiaConfig(aFormat), aSize.width, aSize.height, aStride);
temp.setPixels(aData);
if (!temp.copyTo(&mBitmap, GfxFormatToSkiaConfig(aFormat))) {
return false;
}
if (aFormat == FORMAT_B8G8R8X8) {
mBitmap.lockPixels();
// We have to manually set the A channel to be 255 as Skia doesn't understand BGRX
ConvertBGRXToBGRA(reinterpret_cast<unsigned char*>(mBitmap.getPixels()), aSize, mBitmap.rowBytes());
mBitmap.unlockPixels();
mBitmap.notifyPixelsChanged();
mBitmap.setIsOpaque(true);
}
mSize = aSize;
mFormat = aFormat;
mStride = mBitmap.rowBytes();
return true;
}
unsigned char*
SourceSurfaceSkia::GetData()
{
if (!mLocked) {
mBitmap.lockPixels();
mLocked = true;
}
unsigned char *pixels = (unsigned char *)mBitmap.getPixels();
return pixels;
}
void
SourceSurfaceSkia::DrawTargetWillChange()
{
if (mDrawTarget) {
MaybeUnlock();
mDrawTarget = nullptr;
SkBitmap temp = mBitmap;
mBitmap.reset();
temp.copyTo(&mBitmap, temp.getConfig());
}
}
void
SourceSurfaceSkia::MaybeUnlock()
{
if (mLocked) {
mBitmap.unlockPixels();
mLocked = false;
}
}
}
}