2011-11-02 23:55:03 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
2012-05-21 15:12:37 +04:00
|
|
|
* 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/. */
|
2011-11-02 23:55:03 +04:00
|
|
|
|
|
|
|
|
|
|
|
#include "Logging.h"
|
|
|
|
#include "SourceSurfaceSkia.h"
|
|
|
|
#include "HelpersSkia.h"
|
2011-11-02 23:55:03 +04:00
|
|
|
#include "DrawTargetSkia.h"
|
2013-11-03 20:28:30 +04:00
|
|
|
#include "DataSurfaceHelpers.h"
|
2016-10-25 05:40:59 +03:00
|
|
|
#include "skia/include/core/SkData.h"
|
|
|
|
#include "mozilla/CheckedInt.h"
|
2011-11-02 23:55:03 +04:00
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
namespace gfx {
|
|
|
|
|
|
|
|
SourceSurfaceSkia::SourceSurfaceSkia()
|
2016-10-25 05:40:59 +03:00
|
|
|
: mDrawTarget(nullptr)
|
2011-11-02 23:55:03 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
SourceSurfaceSkia::~SourceSurfaceSkia()
|
|
|
|
{
|
2015-05-26 10:00:19 +03:00
|
|
|
if (mDrawTarget) {
|
|
|
|
mDrawTarget->SnapshotDestroyed();
|
|
|
|
mDrawTarget = nullptr;
|
|
|
|
}
|
2011-11-02 23:55:03 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
IntSize
|
|
|
|
SourceSurfaceSkia::GetSize() const
|
|
|
|
{
|
|
|
|
return mSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
SurfaceFormat
|
|
|
|
SourceSurfaceSkia::GetFormat() const
|
|
|
|
{
|
|
|
|
return mFormat;
|
|
|
|
}
|
|
|
|
|
2016-01-21 17:50:43 +03:00
|
|
|
bool
|
2011-11-02 23:55:03 +04:00
|
|
|
SourceSurfaceSkia::InitFromData(unsigned char* aData,
|
|
|
|
const IntSize &aSize,
|
|
|
|
int32_t aStride,
|
|
|
|
SurfaceFormat aFormat)
|
|
|
|
{
|
2016-10-25 05:40:59 +03:00
|
|
|
SkPixmap pixmap(MakeSkiaImageInfo(aSize, aFormat), aData, aStride);
|
|
|
|
mImage = SkImage::MakeRasterCopy(pixmap);
|
|
|
|
if (!mImage) {
|
2011-11-02 23:55:03 +04:00
|
|
|
return false;
|
|
|
|
}
|
2012-09-13 03:07:53 +04:00
|
|
|
|
2011-11-02 23:55:03 +04:00
|
|
|
mSize = aSize;
|
|
|
|
mFormat = aFormat;
|
2016-10-25 05:40:59 +03:00
|
|
|
mStride = aStride;
|
2011-11-02 23:55:03 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-10-25 02:45:46 +03:00
|
|
|
bool
|
2016-11-15 01:16:18 +03:00
|
|
|
SourceSurfaceSkia::InitFromImage(const sk_sp<SkImage>& aImage,
|
2016-10-25 05:40:59 +03:00
|
|
|
SurfaceFormat aFormat,
|
|
|
|
DrawTargetSkia* aOwner)
|
2016-10-25 02:45:46 +03:00
|
|
|
{
|
2016-10-25 05:40:59 +03:00
|
|
|
if (!aImage) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
mSize = IntSize(aImage->width(), aImage->height());
|
|
|
|
|
|
|
|
// For the raster image case, we want to use the format and stride
|
|
|
|
// information that the underlying raster image is using, which is
|
|
|
|
// reliable.
|
|
|
|
// For the GPU case (for which peekPixels is false), we can't easily
|
|
|
|
// figure this information out. It is better to report the originally
|
|
|
|
// intended format and stride that we will convert to if this GPU
|
|
|
|
// image is ever read back into a raster image.
|
|
|
|
SkPixmap pixmap;
|
|
|
|
if (aImage->peekPixels(&pixmap)) {
|
|
|
|
mFormat =
|
|
|
|
aFormat != SurfaceFormat::UNKNOWN ?
|
|
|
|
aFormat :
|
|
|
|
SkiaColorTypeToGfxFormat(pixmap.colorType(), pixmap.alphaType());
|
|
|
|
mStride = pixmap.rowBytes();
|
|
|
|
} else if (aFormat != SurfaceFormat::UNKNOWN) {
|
|
|
|
mFormat = aFormat;
|
|
|
|
SkImageInfo info = MakeSkiaImageInfo(mSize, mFormat);
|
|
|
|
mStride = SkAlign4(info.minRowBytes());
|
|
|
|
} else {
|
2016-01-21 17:51:40 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-10-25 05:40:59 +03:00
|
|
|
mImage = aImage;
|
|
|
|
|
|
|
|
if (aOwner) {
|
|
|
|
mDrawTarget = aOwner;
|
|
|
|
}
|
2016-01-21 17:51:40 +03:00
|
|
|
|
2014-11-11 23:14:00 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-10-25 05:40:59 +03:00
|
|
|
uint8_t*
|
2011-11-02 23:55:03 +04:00
|
|
|
SourceSurfaceSkia::GetData()
|
|
|
|
{
|
2016-10-25 05:40:59 +03:00
|
|
|
#ifdef USE_SKIA_GPU
|
|
|
|
if (mImage->isTextureBacked()) {
|
|
|
|
sk_sp<SkImage> raster;
|
|
|
|
CheckedInt<size_t> size = mStride;
|
|
|
|
size *= mSize.height;
|
|
|
|
if (size.isValid()) {
|
|
|
|
if (sk_sp<SkData> data = SkData::MakeUninitialized(size.value())) {
|
|
|
|
SkImageInfo info = MakeSkiaImageInfo(mSize, mFormat);
|
|
|
|
if (mImage->readPixels(info, data->writable_data(), mStride, 0, 0, SkImage::kDisallow_CachingHint)) {
|
|
|
|
raster = SkImage::MakeRasterData(info, data, mStride);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-12-20 20:37:19 +03:00
|
|
|
if (raster) {
|
|
|
|
mImage = raster;
|
|
|
|
} else {
|
2016-10-25 05:40:59 +03:00
|
|
|
gfxCriticalError() << "Failed making Skia raster image for GPU surface";
|
|
|
|
}
|
2016-10-24 22:22:20 +03:00
|
|
|
}
|
2016-10-25 05:40:59 +03:00
|
|
|
#endif
|
|
|
|
SkPixmap pixmap;
|
|
|
|
if (!mImage->peekPixels(&pixmap)) {
|
|
|
|
gfxCriticalError() << "Failed accessing pixels for Skia raster image";
|
|
|
|
}
|
|
|
|
return reinterpret_cast<uint8_t*>(pixmap.writable_addr());
|
2011-11-02 23:55:03 +04:00
|
|
|
}
|
|
|
|
|
2011-11-02 23:55:03 +04:00
|
|
|
void
|
|
|
|
SourceSurfaceSkia::DrawTargetWillChange()
|
|
|
|
{
|
2015-05-26 10:00:19 +03:00
|
|
|
if (mDrawTarget) {
|
2016-10-25 05:40:59 +03:00
|
|
|
// Raster snapshots do not use Skia's internal copy-on-write mechanism,
|
|
|
|
// so we need to do an explicit copy here.
|
|
|
|
// GPU snapshots, for which peekPixels is false, will already be dealt
|
|
|
|
// with automatically via the internal copy-on-write mechanism, so we
|
|
|
|
// don't need to do anything for them here.
|
|
|
|
SkPixmap pixmap;
|
|
|
|
if (mImage->peekPixels(&pixmap)) {
|
|
|
|
mImage = SkImage::MakeRasterCopy(pixmap);
|
|
|
|
if (!mImage) {
|
|
|
|
gfxCriticalError() << "Failed copying Skia raster snapshot";
|
|
|
|
}
|
2016-10-25 02:45:46 +03:00
|
|
|
}
|
2016-10-25 05:40:59 +03:00
|
|
|
mDrawTarget = nullptr;
|
2013-06-18 20:49:05 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-13 18:25:42 +03:00
|
|
|
} // namespace gfx
|
|
|
|
} // namespace mozilla
|