bcfc554fde
Note: The polarity of the staging flag is inverted from usual because a G3 dependency with no SkUserConfig.h relies on the legacy API. Once this lands, we will migrate them and others, then remove the staging API. The inverted staging flag is kind of nice, actually - I may use that pattern in the future. It means less total CLs and it's just as easy to flip the bit on or off during debugging. Bug: skia:104662 Change-Id: I48cba1eeae3e2e6f79918c6d243e0666e68ec71b Reviewed-on: https://skia-review.googlesource.com/c/skia/+/310656 Reviewed-by: Brian Salomon <bsalomon@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com> Commit-Queue: Adlai Holler <adlai@google.com>
321 lines
11 KiB
C++
321 lines
11 KiB
C++
/*
|
|
* Copyright 2016 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#include "gm/gm.h"
|
|
#include "include/codec/SkCodec.h"
|
|
#include "include/core/SkBitmap.h"
|
|
#include "include/core/SkCanvas.h"
|
|
#include "include/core/SkColorSpace.h"
|
|
#include "include/core/SkData.h"
|
|
#include "include/core/SkImage.h"
|
|
#include "include/core/SkImageInfo.h"
|
|
#include "include/core/SkPaint.h"
|
|
#include "include/core/SkPicture.h"
|
|
#include "include/core/SkPictureRecorder.h"
|
|
#include "include/core/SkRect.h"
|
|
#include "include/core/SkRefCnt.h"
|
|
#include "include/core/SkSize.h"
|
|
#include "include/core/SkStream.h"
|
|
#include "include/core/SkString.h"
|
|
#include "include/core/SkTypes.h"
|
|
#include "include/gpu/GrDirectContext.h"
|
|
#include "include/third_party/skcms/skcms.h"
|
|
#include "tools/Resources.h"
|
|
|
|
#include <string.h>
|
|
#include <memory>
|
|
#include <utility>
|
|
|
|
class GrContext;
|
|
|
|
static const int kWidth = 64;
|
|
static const int kHeight = 64;
|
|
|
|
static sk_sp<SkImage> make_raster_image(SkColorType colorType) {
|
|
std::unique_ptr<SkStream> stream(GetResourceAsStream("images/google_chrome.ico"));
|
|
std::unique_ptr<SkCodec> codec = SkCodec::MakeFromStream(std::move(stream));
|
|
if (!codec) {
|
|
return nullptr;
|
|
}
|
|
|
|
SkBitmap bitmap;
|
|
SkImageInfo info = codec->getInfo().makeWH(kWidth, kHeight)
|
|
.makeColorType(colorType)
|
|
.makeAlphaType(kPremul_SkAlphaType);
|
|
bitmap.allocPixels(info);
|
|
codec->getPixels(info, bitmap.getPixels(), bitmap.rowBytes());
|
|
bitmap.setImmutable();
|
|
return SkImage::MakeFromBitmap(bitmap);
|
|
}
|
|
|
|
static sk_sp<SkImage> make_codec_image() {
|
|
sk_sp<SkData> encoded = GetResourceAsData("images/randPixels.png");
|
|
return SkImage::MakeFromEncoded(encoded);
|
|
}
|
|
|
|
static void draw_contents(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
paint.setStyle(SkPaint::kStroke_Style);
|
|
paint.setStrokeWidth(20);
|
|
paint.setColor(0xFF800000);
|
|
canvas->drawCircle(40, 40, 35, paint);
|
|
paint.setColor(0xFF008000);
|
|
canvas->drawCircle(50, 50, 35, paint);
|
|
paint.setColor(0xFF000080);
|
|
canvas->drawCircle(60, 60, 35, paint);
|
|
}
|
|
|
|
static sk_sp<SkImage> make_picture_image() {
|
|
SkPictureRecorder recorder;
|
|
draw_contents(recorder.beginRecording(SkRect::MakeIWH(kWidth, kHeight)));
|
|
return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(),
|
|
SkISize::Make(kWidth, kHeight), nullptr, nullptr,
|
|
SkImage::BitDepth::kU8,
|
|
SkColorSpace::MakeSRGB());
|
|
}
|
|
|
|
static sk_sp<SkColorSpace> make_parametric_transfer_fn(const SkColorSpacePrimaries& primaries) {
|
|
skcms_Matrix3x3 toXYZD50;
|
|
SkAssertResult(primaries.toXYZD50(&toXYZD50));
|
|
skcms_TransferFunction fn = { 1.8f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f };
|
|
return SkColorSpace::MakeRGB(fn, toXYZD50);
|
|
}
|
|
|
|
static sk_sp<SkColorSpace> make_wide_gamut() {
|
|
// ProPhoto
|
|
SkColorSpacePrimaries primaries;
|
|
primaries.fRX = 0.7347f;
|
|
primaries.fRY = 0.2653f;
|
|
primaries.fGX = 0.1596f;
|
|
primaries.fGY = 0.8404f;
|
|
primaries.fBX = 0.0366f;
|
|
primaries.fBY = 0.0001f;
|
|
primaries.fWX = 0.34567f;
|
|
primaries.fWY = 0.35850f;
|
|
return make_parametric_transfer_fn(primaries);
|
|
}
|
|
|
|
static sk_sp<SkColorSpace> make_small_gamut() {
|
|
SkColorSpacePrimaries primaries;
|
|
primaries.fRX = 0.50f;
|
|
primaries.fRY = 0.33f;
|
|
primaries.fGX = 0.30f;
|
|
primaries.fGY = 0.50f;
|
|
primaries.fBX = 0.25f;
|
|
primaries.fBY = 0.16f;
|
|
primaries.fWX = 0.3127f;
|
|
primaries.fWY = 0.3290f;
|
|
return make_parametric_transfer_fn(primaries);
|
|
}
|
|
|
|
static void draw_image(GrDirectContext* dContext, SkCanvas* canvas, SkImage* image,
|
|
SkColorType dstColorType, SkAlphaType dstAlphaType,
|
|
sk_sp<SkColorSpace> dstColorSpace, SkImage::CachingHint hint) {
|
|
size_t rowBytes = image->width() * SkColorTypeBytesPerPixel(dstColorType);
|
|
sk_sp<SkData> data = SkData::MakeUninitialized(rowBytes * image->height());
|
|
SkImageInfo dstInfo = SkImageInfo::Make(image->width(), image->height(), dstColorType,
|
|
dstAlphaType, dstColorSpace);
|
|
if (!image->readPixels(dContext, dstInfo, data->writable_data(), rowBytes, 0, 0, hint)) {
|
|
memset(data->writable_data(), 0, rowBytes * image->height());
|
|
}
|
|
|
|
// Now that we have called readPixels(), dump the raw pixels into an srgb image.
|
|
sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
|
|
sk_sp<SkImage> raw = SkImage::MakeRasterData(dstInfo.makeColorSpace(srgb), data, rowBytes);
|
|
canvas->drawImage(raw.get(), 0.0f, 0.0f, nullptr);
|
|
}
|
|
|
|
class ReadPixelsGM : public skiagm::GM {
|
|
public:
|
|
ReadPixelsGM() {}
|
|
|
|
protected:
|
|
SkString onShortName() override {
|
|
return SkString("readpixels");
|
|
}
|
|
|
|
SkISize onISize() override {
|
|
return SkISize::Make(6 * kWidth, 9 * kHeight);
|
|
}
|
|
|
|
void onDraw(SkCanvas* canvas) override {
|
|
const SkAlphaType alphaTypes[] = {
|
|
kUnpremul_SkAlphaType,
|
|
kPremul_SkAlphaType,
|
|
};
|
|
const SkColorType colorTypes[] = {
|
|
kRGBA_8888_SkColorType,
|
|
kBGRA_8888_SkColorType,
|
|
kRGBA_F16_SkColorType,
|
|
};
|
|
const sk_sp<SkColorSpace> colorSpaces[] = {
|
|
make_wide_gamut(),
|
|
SkColorSpace::MakeSRGB(),
|
|
make_small_gamut(),
|
|
};
|
|
|
|
for (const sk_sp<SkColorSpace>& dstColorSpace : colorSpaces) {
|
|
for (SkColorType srcColorType : colorTypes) {
|
|
canvas->save();
|
|
sk_sp<SkImage> image = make_raster_image(srcColorType);
|
|
if (!image) {
|
|
continue;
|
|
}
|
|
auto dContext = GrAsDirectContext(canvas->recordingContext());
|
|
if (dContext) {
|
|
image = image->makeTextureImage(dContext);
|
|
}
|
|
if (image) {
|
|
for (SkColorType dstColorType : colorTypes) {
|
|
for (SkAlphaType dstAlphaType : alphaTypes) {
|
|
draw_image(dContext, canvas, image.get(), dstColorType, dstAlphaType,
|
|
dstColorSpace, SkImage::kAllow_CachingHint);
|
|
canvas->translate((float)kWidth, 0.0f);
|
|
}
|
|
}
|
|
}
|
|
canvas->restore();
|
|
canvas->translate(0.0f, (float) kHeight);
|
|
}
|
|
}
|
|
}
|
|
|
|
private:
|
|
typedef skiagm::GM INHERITED;
|
|
};
|
|
DEF_GM( return new ReadPixelsGM; )
|
|
|
|
class ReadPixelsCodecGM : public skiagm::GM {
|
|
public:
|
|
ReadPixelsCodecGM() {}
|
|
|
|
protected:
|
|
SkString onShortName() override {
|
|
return SkString("readpixelscodec");
|
|
}
|
|
|
|
SkISize onISize() override {
|
|
return SkISize::Make(3 * (kEncodedWidth + 1), 12 * (kEncodedHeight + 1));
|
|
}
|
|
|
|
DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
|
|
if (!canvas->imageInfo().colorSpace()) {
|
|
*errorMsg = "This gm is only interesting in color correct modes.";
|
|
return DrawResult::kSkip;
|
|
}
|
|
|
|
const SkAlphaType alphaTypes[] = {
|
|
kUnpremul_SkAlphaType,
|
|
kPremul_SkAlphaType,
|
|
};
|
|
const SkColorType colorTypes[] = {
|
|
kRGBA_8888_SkColorType,
|
|
kBGRA_8888_SkColorType,
|
|
kRGBA_F16_SkColorType,
|
|
};
|
|
const sk_sp<SkColorSpace> colorSpaces[] = {
|
|
make_wide_gamut(),
|
|
SkColorSpace::MakeSRGB(),
|
|
make_small_gamut(),
|
|
};
|
|
const SkImage::CachingHint hints[] = {
|
|
SkImage::kAllow_CachingHint,
|
|
SkImage::kDisallow_CachingHint,
|
|
};
|
|
|
|
sk_sp<SkImage> image = make_codec_image();
|
|
for (const sk_sp<SkColorSpace>& dstColorSpace : colorSpaces) {
|
|
canvas->save();
|
|
for (SkColorType dstColorType : colorTypes) {
|
|
for (SkAlphaType dstAlphaType : alphaTypes) {
|
|
for (SkImage::CachingHint hint : hints) {
|
|
draw_image(nullptr, canvas, image.get(), dstColorType, dstAlphaType,
|
|
dstColorSpace, hint);
|
|
canvas->translate(0.0f, (float) kEncodedHeight + 1);
|
|
}
|
|
}
|
|
}
|
|
canvas->restore();
|
|
canvas->translate((float) kEncodedWidth + 1, 0.0f);
|
|
}
|
|
return DrawResult::kOk;
|
|
}
|
|
|
|
private:
|
|
static const int kEncodedWidth = 8;
|
|
static const int kEncodedHeight = 8;
|
|
|
|
typedef skiagm::GM INHERITED;
|
|
};
|
|
DEF_GM( return new ReadPixelsCodecGM; )
|
|
|
|
class ReadPixelsPictureGM : public skiagm::GM {
|
|
public:
|
|
ReadPixelsPictureGM() {}
|
|
|
|
protected:
|
|
SkString onShortName() override {
|
|
return SkString("readpixelspicture");
|
|
}
|
|
|
|
SkISize onISize() override {
|
|
return SkISize::Make(3 * kWidth, 12 * kHeight);
|
|
}
|
|
|
|
DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
|
|
if (!canvas->imageInfo().colorSpace()) {
|
|
*errorMsg = "This gm is only interesting in color correct modes.";
|
|
return DrawResult::kSkip;
|
|
}
|
|
|
|
const sk_sp<SkImage> images[] = {
|
|
make_picture_image(),
|
|
};
|
|
const SkAlphaType alphaTypes[] = {
|
|
kUnpremul_SkAlphaType,
|
|
kPremul_SkAlphaType,
|
|
};
|
|
const SkColorType colorTypes[] = {
|
|
kRGBA_8888_SkColorType,
|
|
kBGRA_8888_SkColorType,
|
|
kRGBA_F16_SkColorType,
|
|
};
|
|
const sk_sp<SkColorSpace> colorSpaces[] = {
|
|
make_wide_gamut(),
|
|
SkColorSpace::MakeSRGB(),
|
|
make_small_gamut(),
|
|
};
|
|
const SkImage::CachingHint hints[] = {
|
|
SkImage::kAllow_CachingHint,
|
|
SkImage::kDisallow_CachingHint,
|
|
};
|
|
|
|
for (const sk_sp<SkImage>& image : images) {
|
|
for (const sk_sp<SkColorSpace>& dstColorSpace : colorSpaces) {
|
|
canvas->save();
|
|
for (SkColorType dstColorType : colorTypes) {
|
|
for (SkAlphaType dstAlphaType : alphaTypes) {
|
|
for (SkImage::CachingHint hint : hints) {
|
|
draw_image(nullptr, canvas, image.get(), dstColorType, dstAlphaType,
|
|
dstColorSpace, hint);
|
|
canvas->translate(0.0f, (float) kHeight);
|
|
}
|
|
}
|
|
}
|
|
canvas->restore();
|
|
canvas->translate((float) kWidth, 0.0f);
|
|
}
|
|
}
|
|
return DrawResult::kOk;
|
|
}
|
|
|
|
private:
|
|
|
|
typedef skiagm::GM INHERITED;
|
|
};
|
|
DEF_GM( return new ReadPixelsPictureGM; )
|