SkSurfaceProps now has a gamma-correct ("AllowSRGBInputs") flag. That's propagated in a few places so that the backend can do the right thing for L32 vs S32 mode.

Also added SkSurfaceProps to SkSpecialImage, so that Image -> Surface conversion can preserve the desired behavior during filtering.

Many small changes, including a bunch of comments about places where we may be losing information right now. My approach was to ensure that if anything fails, it will always fall back to "legacy" mode - gamma-correctness is opt-in, so I'll just have to feed things through as missing cases are exposed.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1838953007

Review URL: https://codereview.chromium.org/1845283003
This commit is contained in:
brianosman 2016-04-06 07:38:23 -07:00 committed by Commit bot
parent 1817d282cd
commit 898235c486
48 changed files with 315 additions and 127 deletions

View File

@ -822,8 +822,8 @@ static Sink* create_sink(const SkCommandLineConfig* config) {
contextOptions = static_cast<GrContextFactory::ContextOptions>(
contextOptions | GrContextFactory::kEnableNVPR_ContextOptions);
}
if (kSRGB_SkColorProfileType == gpuConfig->getProfileType() ||
kRGBA_F16_SkColorType == gpuConfig->getColorType()) {
if (SkColorAndProfileAreGammaCorrect(gpuConfig->getColorType(),
gpuConfig->getProfileType())) {
contextOptions = static_cast<GrContextFactory::ContextOptions>(
contextOptions | GrContextFactory::kRequireSRGBSupport_ContextOptions);
}
@ -1169,8 +1169,7 @@ struct Task {
const SkBitmap* bitmap) {
bool gammaCorrect = false;
if (bitmap) {
gammaCorrect = bitmap->profileType() == kSRGB_SkColorProfileType
|| bitmap-> colorType() == kRGBA_F16_SkColorType;
gammaCorrect = SkImageInfoIsGammaCorrect(bitmap->info());
}
JsonWriter::BitmapResult result;

View File

@ -36,6 +36,9 @@ static inline sk_sp<SkSurface> NewGpuSurface(
int samples,
bool useDIText) {
uint32_t flags = useDIText ? SkSurfaceProps::kUseDeviceIndependentFonts_Flag : 0;
if (SkImageInfoIsGammaCorrect(info)) {
flags |= SkSurfaceProps::kAllowSRGBInputs_Flag;
}
SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType);
return SkSurface::MakeRenderTarget(grFactory->get(type, options), SkBudgeted::kNo,
info, samples, &props);

View File

@ -104,7 +104,8 @@ protected:
} else {
skPaint.setColor(kPaintColors[paintType]);
}
SkAssertResult(SkPaintToGrPaint(context, skPaint, viewMatrix, &grPaint));
// SRGBTODO: No sRGB inputs allowed here?
SkAssertResult(SkPaintToGrPaint(context, skPaint, viewMatrix, false, &grPaint));
GrConstColorProcessor::InputMode mode = (GrConstColorProcessor::InputMode) m;
GrColor color = kColors[procColor];

View File

@ -48,8 +48,12 @@ protected:
// set up offscreen rendering with distance field text
#if SK_SUPPORT_GPU
GrContext* ctx = inputCanvas->getGrContext();
SkImageInfo info = SkImageInfo::MakeN32Premul(onISize());
SkSurfaceProps props(SkSurfaceProps::kUseDeviceIndependentFonts_Flag,
SkImageInfo info = SkImageInfo::MakeN32Premul(onISize(),
inputCanvas->imageInfo().profileType());
SkSurfaceProps canvasProps(SkSurfaceProps::kLegacyFontHost_InitType);
uint32_t allowSRGBInputs = inputCanvas->getProps(&canvasProps)
? canvasProps.flags() & SkSurfaceProps::kAllowSRGBInputs_Flag : 0;
SkSurfaceProps props(SkSurfaceProps::kUseDeviceIndependentFonts_Flag | allowSRGBInputs,
SkSurfaceProps::kLegacyFontHost_InitType);
auto surface(SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info, 0, &props));
SkCanvas* canvas = surface ? surface->getCanvas() : inputCanvas;

View File

@ -22,7 +22,7 @@ static sk_sp<SkShader> make_shader() {
}
static sk_sp<SkSurface> make_surface(GrContext* ctx, const SkImageInfo& info, SkPixelGeometry geo,
int disallowAA, int disallowDither) {
int disallowAA, int disallowDither, bool allowSRGBInputs) {
uint32_t flags = 0;
if (disallowAA) {
flags |= SkSurfaceProps::kDisallowAntiAlias_Flag;
@ -30,6 +30,9 @@ static sk_sp<SkSurface> make_surface(GrContext* ctx, const SkImageInfo& info, Sk
if (disallowDither) {
flags |= SkSurfaceProps::kDisallowDither_Flag;
}
if (allowSRGBInputs) {
flags |= SkSurfaceProps::kAllowSRGBInputs_Flag;
}
SkSurfaceProps props(flags, geo);
if (ctx) {
@ -74,7 +77,10 @@ protected:
GrContext* ctx = canvas->getGrContext();
// must be opaque to have a hope of testing LCD text
const SkImageInfo info = SkImageInfo::MakeN32(W, H, kOpaque_SkAlphaType);
const SkImageInfo info = SkImageInfo::MakeN32(W, H, kOpaque_SkAlphaType,
canvas->imageInfo().profileType());
SkSurfaceProps canvasProps(SkSurfaceProps::kLegacyFontHost_InitType);
bool allowSRGBInputs = canvas->getProps(&canvasProps) && canvasProps.allowSRGBInputs();
const struct {
SkPixelGeometry fGeo;
@ -92,7 +98,8 @@ protected:
for (int disallowDither = 0; disallowDither <= 1; ++disallowDither) {
SkScalar y = 0;
for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) {
auto surface(make_surface(ctx, info, rec[i].fGeo, disallowAA, disallowDither));
auto surface(make_surface(ctx, info, rec[i].fGeo, disallowAA, disallowDither,
allowSRGBInputs));
test_draw(surface->getCanvas(), rec[i].fLabel);
surface->draw(canvas, x, y, nullptr);
y += H;

View File

@ -42,8 +42,11 @@ protected:
SkAutoTUnref<const SkTextBlob> blob(builder.build());
SkImageInfo info = SkImageInfo::MakeN32Premul(200, 200);
SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
SkImageInfo info = SkImageInfo::MakeN32Premul(200, 200, canvas->imageInfo().profileType());
SkSurfaceProps canvasProps(SkSurfaceProps::kLegacyFontHost_InitType);
uint32_t allowSRGBInputs = canvas->getProps(&canvasProps)
? canvasProps.flags() & SkSurfaceProps::kAllowSRGBInputs_Flag : 0;
SkSurfaceProps props(allowSRGBInputs, kUnknown_SkPixelGeometry);
auto surface(canvas->makeSurface(info, &props));
if (surface) {
SkCanvas* c = surface->getCanvas();

View File

@ -103,8 +103,12 @@ protected:
#if SK_SUPPORT_GPU
// Create a new Canvas to enable DFT
GrContext* ctx = inputCanvas->getGrContext();
SkImageInfo info = SkImageInfo::MakeN32Premul(onISize());
SkSurfaceProps props(SkSurfaceProps::kUseDeviceIndependentFonts_Flag,
SkImageInfo info = SkImageInfo::MakeN32Premul(onISize(),
inputCanvas->imageInfo().profileType());
SkSurfaceProps canvasProps(SkSurfaceProps::kLegacyFontHost_InitType);
uint32_t allowSRGBInputs = inputCanvas->getProps(&canvasProps)
? canvasProps.flags() & SkSurfaceProps::kAllowSRGBInputs_Flag : 0;
SkSurfaceProps props(SkSurfaceProps::kUseDeviceIndependentFonts_Flag | allowSRGBInputs,
SkSurfaceProps::kLegacyFontHost_InitType);
surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info, 0, &props);
canvas = surface.get() ? surface->getCanvas() : inputCanvas;

View File

@ -100,8 +100,12 @@ protected:
canvas->drawColor(sk_tool_utils::color_to_565(SK_ColorWHITE));
SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight);
SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight,
canvas->imageInfo().profileType());
SkSurfaceProps canvasProps(SkSurfaceProps::kLegacyFontHost_InitType);
uint32_t allowSRGBInputs = canvas->getProps(&canvasProps)
? canvasProps.flags() & SkSurfaceProps::kAllowSRGBInputs_Flag : 0;
SkSurfaceProps props(allowSRGBInputs, kUnknown_SkPixelGeometry);
auto surface(canvas->makeSurface(info, &props));
if (surface) {
SkPaint paint;

View File

@ -128,7 +128,9 @@ private:
SkImageInfo baseInfo = baseCanvas->imageInfo();
SkImageInfo info = SkImageInfo::Make(w, h, baseInfo.colorType(), baseInfo.alphaType(),
baseInfo.profileType());
return SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info, 0, nullptr);
SkSurfaceProps canvasProps(SkSurfaceProps::kLegacyFontHost_InitType);
baseCanvas->getProps(&canvasProps);
return SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info, 0, &canvasProps);
#else
return nullptr;
#endif

View File

@ -122,6 +122,13 @@ public:
*/
SkImageInfo imageInfo() const;
/**
* If the canvas is backed by pixels (cpu or gpu), this writes a copy of the SurfaceProps
* for the canvas to the location supplied by the caller, and returns true. Otherwise,
* return false and leave the supplied props unchanged.
*/
bool getProps(SkSurfaceProps*) const;
///////////////////////////////////////////////////////////////////////////
/**

View File

@ -40,6 +40,13 @@ public:
*/
virtual SkImageInfo imageInfo() const;
/**
* Return SurfaceProps for this device.
*/
const SkSurfaceProps& surfaceProps() const {
return fSurfaceProps;
}
/**
* Return the bounds of the device in the coordinate space of the root
* canvas. The root device will have its top-left at 0,0, but other devices
@ -317,10 +324,6 @@ protected:
virtual bool onAccessPixels(SkPixmap*) { return false; }
const SkSurfaceProps& surfaceProps() const {
return fSurfaceProps;
}
/**
* PRIVATE / EXPERIMENTAL -- do not call
* This entry point gives the backend an opportunity to take over the rendering

View File

@ -318,4 +318,14 @@ private:
{}
};
///////////////////////////////////////////////////////////////////////////////
static inline bool SkColorAndProfileAreGammaCorrect(SkColorType ct, SkColorProfileType pt) {
return kSRGB_SkColorProfileType == pt || kRGBA_F16_SkColorType == ct;
}
static inline bool SkImageInfoIsGammaCorrect(const SkImageInfo& info) {
return SkColorAndProfileAreGammaCorrect(info.colorType(), info.profileType());
}
#endif

View File

@ -54,6 +54,17 @@ public:
kDisallowAntiAlias_Flag = 1 << 0,
kDisallowDither_Flag = 1 << 1,
kUseDeviceIndependentFonts_Flag = 1 << 2,
/**
* This flag causes sRGB inputs to the color pipeline (images and other sRGB-tagged
* colors) to be gamma-corrected (converted to linear) before use. Without this flag,
* texture scaling and filtering is not gamma correct, preserving the behavior of Skia
* up through 2015.
*
* It is recommended to enable this flag when rendering to an sRGB or floating point
* surface.
*/
kAllowSRGBInputs_Flag = 1 << 3,
};
/** Deprecated alias used by Chromium. Will be removed. */
static const Flags kUseDistanceFieldFonts_Flag = kUseDeviceIndependentFonts_Flag;
@ -75,6 +86,7 @@ public:
bool isUseDeviceIndependentFonts() const {
return SkToBool(fFlags & kUseDeviceIndependentFonts_Flag);
}
bool allowSRGBInputs() const { return SkToBool(fFlags & kAllowSRGBInputs_Flag); }
private:
SkSurfaceProps();

View File

@ -276,6 +276,7 @@ public:
int width() const { return fRenderTarget->width(); }
int height() const { return fRenderTarget->height(); }
int numColorSamples() const { return fRenderTarget->numColorSamples(); }
bool allowSRGBInputs() const { return fSurfaceProps.allowSRGBInputs(); }
GrRenderTarget* accessRenderTarget() { return fRenderTarget; }

View File

@ -63,6 +63,13 @@ public:
void setDisableOutputConversionToSRGB(bool srgb) { fDisableOutputConversionToSRGB = srgb; }
bool getDisableOutputConversionToSRGB() const { return fDisableOutputConversionToSRGB; }
/**
* Should sRGB inputs be allowed to perform sRGB to linear conversion. With this flag
* set to false, sRGB textures will be treated as linear (including filtering).
*/
void setAllowSRGBInputs(bool allowSRGBInputs) { fAllowSRGBInputs = allowSRGBInputs; }
bool getAllowSRGBInputs() const { return fAllowSRGBInputs; }
const GrXPFactory* setXPFactory(const GrXPFactory* xpFactory) {
fXPFactory.reset(SkSafeRef(xpFactory));
return xpFactory;
@ -120,6 +127,7 @@ public:
GrPaint& operator=(const GrPaint& paint) {
fAntiAlias = paint.fAntiAlias;
fDisableOutputConversionToSRGB = paint.fDisableOutputConversionToSRGB;
fAllowSRGBInputs = paint.fAllowSRGBInputs;
fColor = paint.fColor;
this->resetFragmentProcessors();
@ -163,6 +171,7 @@ private:
bool fAntiAlias;
bool fDisableOutputConversionToSRGB;
bool fAllowSRGBInputs;
GrColor fColor;
};

View File

@ -399,16 +399,6 @@ static inline bool GrPixelConfigIsAlphaOnly(GrPixelConfig config) {
}
}
static inline bool GrAllowSRGBForDestinationPixelConfig(GrPixelConfig config) {
switch (config) {
case kRGBA_8888_GrPixelConfig:
case kBGRA_8888_GrPixelConfig:
return false;
default:
return true;
}
}
/**
* Optional bitfield flags that can be set on GrSurfaceDesc (below).
*/

View File

@ -1334,6 +1334,18 @@ SkImageInfo SkCanvas::imageInfo() const {
}
}
bool SkCanvas::getProps(SkSurfaceProps* props) const {
SkBaseDevice* dev = this->getDevice();
if (dev) {
if (props) {
*props = fProps;
}
return true;
} else {
return false;
}
}
#ifdef SK_SUPPORT_LEGACY_PEEKPIXELS_PARMS
const void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) {
SkPixmap pmap;
@ -1406,7 +1418,8 @@ void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
SkAutoTUnref<SkImageFilter::Cache> cache(dstDev->getImageFilterCache());
SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
sk_sp<SkSpecialImage> srcImg(SkSpecialImage::internal_fromBM(&proxy, srcBM));
sk_sp<SkSpecialImage> srcImg(SkSpecialImage::internal_fromBM(&proxy, srcBM,
&dstDev->surfaceProps()));
if (!srcImg) {
continue; // something disastrous happened
}

View File

@ -418,7 +418,8 @@ void SkBaseDevice::drawSpriteWithFilter(const SkDraw& draw, const SkBitmap& bitm
SkAutoTUnref<SkImageFilter::Cache> cache(this->getImageFilterCache());
SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
sk_sp<SkSpecialImage> srcImg(SkSpecialImage::internal_fromBM(&proxy, bitmap));
sk_sp<SkSpecialImage> srcImg(SkSpecialImage::internal_fromBM(&proxy, bitmap,
&this->surfaceProps()));
if (!srcImg) {
return; // something disastrous happened
}

View File

@ -295,7 +295,8 @@ bool SkImageFilter::filterInputDeprecated(int index, Proxy* proxy, const SkBitma
return true;
}
sk_sp<SkSpecialImage> specialSrc(SkSpecialImage::internal_fromBM(proxy, src));
// SRGBTODO: Don't handle sRGB here, in anticipation of this code path being deleted.
sk_sp<SkSpecialImage> specialSrc(SkSpecialImage::internal_fromBM(proxy, src, nullptr));
if (!specialSrc) {
return false;
}
@ -377,7 +378,7 @@ sk_sp<SkSpecialImage> SkImageFilter::onFilterImage(SkSpecialImage* src, const Co
return nullptr;
}
return SkSpecialImage::internal_fromBM(src->internal_getProxy(), resultBM);
return SkSpecialImage::internal_fromBM(src->internal_getProxy(), resultBM, &src->props());
}
bool SkImageFilter::canFilterImageGPU() const {
@ -418,6 +419,7 @@ bool SkImageFilter::filterImageGPUDeprecated(Proxy* proxy, const SkBitmap& src,
SkMatrix matrix(ctx.ctm());
matrix.postTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
GrPaint paint;
// SRGBTODO: Don't handle sRGB here, in anticipation of this code path being deleted.
if (this->asFragmentProcessor(&fp, srcTexture, matrix, bounds)) {
SkASSERT(fp);
paint.addColorFragmentProcessor(fp)->unref();
@ -620,7 +622,8 @@ bool SkImageFilter::filterInputGPUDeprecated(int index, SkImageFilter::Proxy* pr
return true;
}
sk_sp<SkSpecialImage> specialSrc(SkSpecialImage::internal_fromBM(proxy, src));
// SRGBTODO: Don't handle sRGB here, in anticipation of this code path being deleted.
sk_sp<SkSpecialImage> specialSrc(SkSpecialImage::internal_fromBM(proxy, src, nullptr));
if (!specialSrc) {
return false;
}

View File

@ -15,12 +15,14 @@
#include "SkCanvas.h"
#include "SkImage_Base.h"
#include "SkSpecialSurface.h"
#include "SkSurfacePriv.h"
///////////////////////////////////////////////////////////////////////////////
class SkSpecialImage_Base : public SkSpecialImage {
public:
SkSpecialImage_Base(SkImageFilter::Proxy* proxy, const SkIRect& subset, uint32_t uniqueID)
: INHERITED(proxy, subset, uniqueID) {
SkSpecialImage_Base(SkImageFilter::Proxy* proxy, const SkIRect& subset, uint32_t uniqueID,
const SkSurfaceProps* props)
: INHERITED(proxy, subset, uniqueID, props) {
}
virtual ~SkSpecialImage_Base() { }
@ -52,6 +54,16 @@ static inline const SkSpecialImage_Base* as_SIB(const SkSpecialImage* image) {
return static_cast<const SkSpecialImage_Base*>(image);
}
SkSpecialImage::SkSpecialImage(SkImageFilter::Proxy* proxy,
const SkIRect& subset,
uint32_t uniqueID,
const SkSurfaceProps* props)
: fProps(SkSurfacePropsCopyOrDefault(props))
, fSubset(subset)
, fUniqueID(kNeedNewImageUniqueID_SpecialImage == uniqueID ? SkNextID::ImageID() : uniqueID)
, fProxy(proxy) {
}
sk_sp<SkSpecialImage> SkSpecialImage::makeTextureImage(SkImageFilter::Proxy* proxy,
GrContext* context) {
#if SK_SUPPORT_GPU
@ -68,7 +80,7 @@ sk_sp<SkSpecialImage> SkSpecialImage::makeTextureImage(SkImageFilter::Proxy* pro
}
if (bmp.empty()) {
return SkSpecialImage::MakeFromRaster(proxy, SkIRect::MakeEmpty(), bmp);
return SkSpecialImage::MakeFromRaster(proxy, SkIRect::MakeEmpty(), bmp, &this->props());
}
SkAutoTUnref<GrTexture> resultTex(
@ -82,7 +94,7 @@ sk_sp<SkSpecialImage> SkSpecialImage::makeTextureImage(SkImageFilter::Proxy* pro
return SkSpecialImage::MakeFromGpu(proxy,
SkIRect::MakeWH(resultTex->width(), resultTex->height()),
this->uniqueID(),
resultTex, at);
resultTex, &this->props(), at);
#else
return nullptr;
#endif
@ -126,16 +138,18 @@ sk_sp<SkImage> SkSpecialImage::makeTightSubset(const SkIRect& subset) const {
#endif
sk_sp<SkSpecialImage> SkSpecialImage::internal_fromBM(SkImageFilter::Proxy* proxy,
const SkBitmap& src) {
const SkBitmap& src,
const SkSurfaceProps* props) {
// Need to test offset case! (see skbug.com/4967)
if (src.getTexture()) {
return SkSpecialImage::MakeFromGpu(proxy,
src.bounds(),
src.getGenerationID(),
src.getTexture());
src.getTexture(),
props);
}
return SkSpecialImage::MakeFromRaster(proxy, src.bounds(), src);
return SkSpecialImage::MakeFromRaster(proxy, src.bounds(), src, props);
}
bool SkSpecialImage::internal_getBM(SkBitmap* result) {
@ -160,8 +174,9 @@ class SkSpecialImage_Image : public SkSpecialImage_Base {
public:
SkSpecialImage_Image(SkImageFilter::Proxy* proxy,
const SkIRect& subset,
sk_sp<SkImage> image)
: INHERITED(proxy, subset, image->uniqueID())
sk_sp<SkImage> image,
const SkSurfaceProps* props)
: INHERITED(proxy, subset, image->uniqueID(), props)
, fImage(image) {
}
@ -240,7 +255,8 @@ public:
return SkSpecialImage::MakeFromImage(this->internal_getProxy(),
SkIRect::MakeWH(subset.width(), subset.height()),
subsetImg);
subsetImg,
&this->props());
}
sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
@ -279,10 +295,11 @@ static bool rect_fits(const SkIRect& rect, int width, int height) {
sk_sp<SkSpecialImage> SkSpecialImage::MakeFromImage(SkImageFilter::Proxy* proxy,
const SkIRect& subset,
sk_sp<SkImage> image) {
sk_sp<SkImage> image,
const SkSurfaceProps* props) {
SkASSERT(rect_fits(subset, image->width(), image->height()));
return sk_make_sp<SkSpecialImage_Image>(proxy, subset, image);
return sk_make_sp<SkSpecialImage_Image>(proxy, subset, image, props);
}
///////////////////////////////////////////////////////////////////////////////
@ -292,8 +309,9 @@ sk_sp<SkSpecialImage> SkSpecialImage::MakeFromImage(SkImageFilter::Proxy* proxy,
class SkSpecialImage_Raster : public SkSpecialImage_Base {
public:
SkSpecialImage_Raster(SkImageFilter::Proxy* proxy, const SkIRect& subset, const SkBitmap& bm)
: INHERITED(proxy, subset, bm.getGenerationID())
SkSpecialImage_Raster(SkImageFilter::Proxy* proxy, const SkIRect& subset, const SkBitmap& bm,
const SkSurfaceProps* props)
: INHERITED(proxy, subset, bm.getGenerationID(), props)
, fBitmap(bm) {
if (bm.pixelRef() && bm.pixelRef()->isPreLocked()) {
// we only preemptively lock if there is no chance of triggering something expensive
@ -306,8 +324,9 @@ public:
const SkIRect& subset,
const SkPixmap& pixmap,
RasterReleaseProc releaseProc,
ReleaseContext context)
: INHERITED(proxy, subset, kNeedNewImageUniqueID_SpecialImage) {
ReleaseContext context,
const SkSurfaceProps* props)
: INHERITED(proxy, subset, kNeedNewImageUniqueID_SpecialImage, props) {
fBitmap.installPixels(pixmap.info(), pixmap.writable_addr(),
pixmap.rowBytes(), pixmap.ctable(),
releaseProc, context);
@ -364,7 +383,8 @@ public:
return SkSpecialImage::MakeFromRaster(this->internal_getProxy(),
SkIRect::MakeWH(subset.width(), subset.height()),
subsetBM);
subsetBM,
&this->props());
}
sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
@ -389,23 +409,25 @@ private:
sk_sp<SkSpecialImage> SkSpecialImage::MakeFromRaster(SkImageFilter::Proxy* proxy,
const SkIRect& subset,
const SkBitmap& bm) {
const SkBitmap& bm,
const SkSurfaceProps* props) {
SkASSERT(nullptr == bm.getTexture());
SkASSERT(rect_fits(subset, bm.width(), bm.height()));
return sk_make_sp<SkSpecialImage_Raster>(proxy, subset, bm);
return sk_make_sp<SkSpecialImage_Raster>(proxy, subset, bm, props);
}
sk_sp<SkSpecialImage> SkSpecialImage::MakeFromPixmap(SkImageFilter::Proxy* proxy,
const SkIRect& subset,
const SkPixmap& src,
RasterReleaseProc releaseProc,
ReleaseContext context) {
ReleaseContext context,
const SkSurfaceProps* props) {
if (!src.addr()) {
return nullptr;
}
return sk_make_sp<SkSpecialImage_Raster>(proxy, subset, src, releaseProc, context);
return sk_make_sp<SkSpecialImage_Raster>(proxy, subset, src, releaseProc, context, props);
}
@ -417,8 +439,9 @@ sk_sp<SkSpecialImage> SkSpecialImage::MakeFromPixmap(SkImageFilter::Proxy* proxy
class SkSpecialImage_Gpu : public SkSpecialImage_Base {
public:
SkSpecialImage_Gpu(SkImageFilter::Proxy* proxy, const SkIRect& subset,
uint32_t uniqueID, GrTexture* tex, SkAlphaType at)
: INHERITED(proxy, subset, uniqueID)
uint32_t uniqueID, GrTexture* tex, SkAlphaType at,
const SkSurfaceProps* props)
: INHERITED(proxy, subset, uniqueID, props)
, fTexture(SkRef(tex))
, fAlphaType(at) {
}
@ -496,6 +519,7 @@ public:
subset,
this->uniqueID(),
fTexture,
&this->props(),
fAlphaType);
}
@ -539,9 +563,10 @@ sk_sp<SkSpecialImage> SkSpecialImage::MakeFromGpu(SkImageFilter::Proxy* proxy,
const SkIRect& subset,
uint32_t uniqueID,
GrTexture* tex,
const SkSurfaceProps* props,
SkAlphaType at) {
SkASSERT(rect_fits(subset, tex->width(), tex->height()));
return sk_make_sp<SkSpecialImage_Gpu>(proxy, subset, uniqueID, tex, at);
return sk_make_sp<SkSpecialImage_Gpu>(proxy, subset, uniqueID, tex, at, props);
}
#else
@ -550,6 +575,7 @@ sk_sp<SkSpecialImage> SkSpecialImage::MakeFromGpu(SkImageFilter::Proxy* proxy,
const SkIRect& subset,
uint32_t uniqueID,
GrTexture* tex,
const SkSurfaceProps* props,
SkAlphaType at) {
return nullptr;
}

View File

@ -10,6 +10,7 @@
#include "SkNextID.h"
#include "SkRefCnt.h"
#include "SkSurfaceProps.h"
// remove this when internal_getProxy goes away (see skbug.com/4965)
#include "SkImageFilter.h"
@ -47,6 +48,8 @@ public:
typedef void* ReleaseContext;
typedef void(*RasterReleaseProc)(void* pixels, ReleaseContext);
const SkSurfaceProps& props() const { return fProps; }
int width() const { return fSubset.width(); }
int height() const { return fSubset.height(); }
const SkIRect& subset() const { return fSubset; }
@ -69,20 +72,24 @@ public:
static sk_sp<SkSpecialImage> MakeFromImage(SkImageFilter::Proxy*,
const SkIRect& subset,
sk_sp<SkImage>);
sk_sp<SkImage>,
const SkSurfaceProps* = nullptr);
static sk_sp<SkSpecialImage> MakeFromRaster(SkImageFilter::Proxy*,
const SkIRect& subset,
const SkBitmap&);
const SkBitmap&,
const SkSurfaceProps* = nullptr);
static sk_sp<SkSpecialImage> MakeFromGpu(SkImageFilter::Proxy*,
const SkIRect& subset,
uint32_t uniqueID,
GrTexture*,
const SkSurfaceProps* = nullptr,
SkAlphaType at = kPremul_SkAlphaType);
static sk_sp<SkSpecialImage> MakeFromPixmap(SkImageFilter::Proxy*,
const SkIRect& subset,
const SkPixmap&,
RasterReleaseProc,
ReleaseContext);
ReleaseContext,
const SkSurfaceProps* = nullptr);
/**
* Create a new special surface with a backend that is compatible with this special image.
@ -110,7 +117,8 @@ public:
// These three internal methods will go away (see skbug.com/4965)
bool internal_getBM(SkBitmap* result);
static sk_sp<SkSpecialImage> internal_fromBM(SkImageFilter::Proxy*, const SkBitmap&);
static sk_sp<SkSpecialImage> internal_fromBM(SkImageFilter::Proxy*, const SkBitmap&,
const SkSurfaceProps*);
SkImageFilter::Proxy* internal_getProxy() const;
// TODO: hide this when GrLayerHoister uses SkSpecialImages more fully (see skbug.com/5063)
@ -135,12 +143,8 @@ public:
bool peekPixels(SkPixmap*) const;
protected:
SkSpecialImage(SkImageFilter::Proxy* proxy, const SkIRect& subset, uint32_t uniqueID)
: fSubset(subset)
, fUniqueID(kNeedNewImageUniqueID_SpecialImage == uniqueID ? SkNextID::ImageID()
: uniqueID)
, fProxy(proxy) {
}
SkSpecialImage(SkImageFilter::Proxy*, const SkIRect& subset, uint32_t uniqueID,
const SkSurfaceProps*);
// The following 2 are for testing and shouldn't be used.
friend class TestingSpecialImageAccess;
@ -154,8 +158,9 @@ protected:
SkImageFilter::Proxy* proxy() const { return fProxy; }
private:
const SkIRect fSubset;
const uint32_t fUniqueID;
const SkSurfaceProps fProps;
const SkIRect fSubset;
const uint32_t fUniqueID;
// TODO: remove this ASAP (see skbug.com/4965)
SkImageFilter::Proxy* fProxy;

View File

@ -82,7 +82,8 @@ public:
~SkSpecialSurface_Raster() override { }
sk_sp<SkSpecialImage> onMakeImageSnapshot() override {
return SkSpecialImage::MakeFromRaster(this->proxy(), this->subset(), fBitmap);
return SkSpecialImage::MakeFromRaster(this->proxy(), this->subset(), fBitmap,
&this->props());
}
private:
@ -139,7 +140,8 @@ public:
sk_sp<SkSpecialImage> onMakeImageSnapshot() override {
return SkSpecialImage::MakeFromGpu(this->proxy(), this->subset(),
kNeedNewImageUniqueID_SpecialImage, fTexture);
kNeedNewImageUniqueID_SpecialImage, fTexture,
&this->props());
}
private:

View File

@ -113,6 +113,7 @@ sk_sp<SkSpecialImage> SkBlurImageFilter::onFilterImage(SkSpecialImage* source,
SkAutoTUnref<GrTexture> tex(SkGpuBlurUtils::GaussianBlur(inputTexture->getContext(),
inputTexture,
false,
source->props().allowSRGBInputs(),
SkRect::Make(dstBounds),
&inputBoundsF,
sigma.x(),
@ -124,7 +125,7 @@ sk_sp<SkSpecialImage> SkBlurImageFilter::onFilterImage(SkSpecialImage* source,
return SkSpecialImage::MakeFromGpu(source->internal_getProxy(),
SkIRect::MakeWH(dstBounds.width(), dstBounds.height()),
kNeedNewImageUniqueID_SpecialImage,
tex);
tex, &source->props());
}
#endif
@ -216,7 +217,7 @@ sk_sp<SkSpecialImage> SkBlurImageFilter::onFilterImage(SkSpecialImage* source,
return SkSpecialImage::MakeFromRaster(source->internal_getProxy(),
SkIRect::MakeWH(dstBounds.width(),
dstBounds.height()),
dst);
dst, &source->props());
}

View File

@ -1243,7 +1243,8 @@ bool SkBlurMaskFilterImpl::filterMaskGPU(GrTexture* src,
// gaussianBlur. Otherwise, we need to save it for later compositing.
bool isNormalBlur = (kNormal_SkBlurStyle == fBlurStyle);
*result = SkGpuBlurUtils::GaussianBlur(context, src, isNormalBlur && canOverwriteSrc,
clipRect, nullptr, xformedSigma, xformedSigma);
false, clipRect, nullptr,
xformedSigma, xformedSigma);
if (nullptr == *result) {
return false;
}

View File

@ -431,6 +431,7 @@ bool SkDisplacementMapEffect::filterImageGPUDeprecated(Proxy* proxy, const SkBit
ctx.ctm().mapVectors(&scale, 1);
GrPaint paint;
// SRGBTODO: AllowSRGBInputs?
SkMatrix offsetMatrix = GrCoordTransform::MakeDivByTextureWHMatrix(displacement);
offsetMatrix.preTranslate(SkIntToScalar(colorOffset.fX - displacementOffset.fX),
SkIntToScalar(colorOffset.fY - displacementOffset.fY));

View File

@ -56,6 +56,7 @@ static void convolve_gaussian_1d(GrDrawContext* drawContext,
bool useBounds,
float bounds[2]) {
GrPaint paint;
paint.setAllowSRGBInputs(drawContext->allowSRGBInputs());
SkAutoTUnref<GrFragmentProcessor> conv(GrConvolutionEffect::CreateGaussian(
texture, direction, radius, sigma, useBounds, bounds));
paint.addColorFragmentProcessor(conv);
@ -78,6 +79,7 @@ static void convolve_gaussian_2d(GrDrawContext* drawContext,
SkISize size = SkISize::Make(2 * radiusX + 1, 2 * radiusY + 1);
SkIPoint kernelOffset = SkIPoint::Make(radiusX, radiusY);
GrPaint paint;
paint.setAllowSRGBInputs(drawContext->allowSRGBInputs());
SkIRect bounds;
if (srcBounds) {
srcBounds->roundOut(&bounds);
@ -164,6 +166,7 @@ static void convolve_gaussian(GrDrawContext* drawContext,
GrTexture* GaussianBlur(GrContext* context,
GrTexture* srcTexture,
bool canClobberSrc,
bool allowSRGBInputs,
const SkRect& dstBounds,
const SkRect* srcBounds,
float sigmaX,
@ -229,6 +232,7 @@ GrTexture* GaussianBlur(GrContext* context,
for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
GrPaint paint;
paint.setAllowSRGBInputs(allowSRGBInputs);
SkMatrix matrix;
matrix.setIDiv(srcTexture->width(), srcTexture->height());
SkRect dstRect(srcRect);
@ -268,6 +272,9 @@ GrTexture* GaussianBlur(GrContext* context,
localSrcBounds = srcRect;
}
SkSurfaceProps props(allowSRGBInputs ? SkSurfaceProps::kAllowSRGBInputs_Flag : 0,
SkSurfaceProps::kLegacyFontHost_InitType);
// For really small blurs (certainly no wider than 5x5 on desktop gpus) it is faster to just
// launch a single non separable kernel vs two launches
srcRect = localDstBounds;
@ -277,7 +284,7 @@ GrTexture* GaussianBlur(GrContext* context,
SkASSERT((1 == scaleFactorX) && (1 == scaleFactorY));
SkAutoTUnref<GrDrawContext> dstDrawContext(
context->drawContext(dstTexture->asRenderTarget()));
context->drawContext(dstTexture->asRenderTarget(), &props));
if (!dstDrawContext) {
return nullptr;
}
@ -311,7 +318,7 @@ GrTexture* GaussianBlur(GrContext* context,
}
SkAutoTUnref<GrDrawContext> dstDrawContext(
context->drawContext(dstTexture->asRenderTarget()));
context->drawContext(dstTexture->asRenderTarget(), &props));
if (!dstDrawContext) {
return nullptr;
}
@ -344,7 +351,7 @@ GrTexture* GaussianBlur(GrContext* context,
}
SkAutoTUnref<GrDrawContext> dstDrawContext(
context->drawContext(dstTexture->asRenderTarget()));
context->drawContext(dstTexture->asRenderTarget(), &props));
if (!dstDrawContext) {
return nullptr;
}
@ -375,6 +382,7 @@ GrTexture* GaussianBlur(GrContext* context,
matrix.setIDiv(srcTexture->width(), srcTexture->height());
GrPaint paint;
paint.setAllowSRGBInputs(allowSRGBInputs);
// FIXME: this should be mitchell, not bilinear.
GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
paint.addColorTextureProcessor(srcTexture, matrix, params);

View File

@ -26,6 +26,7 @@ namespace SkGpuBlurUtils {
* @param srcTexture The source texture to be blurred.
* @param canClobberSrc If true, srcTexture may be overwritten, and
* may be returned as the result.
* @param allowSRGBInputs Should sRGB inputs be allowed to perform sRGB to linear conversion.
* @param dstBounds The destination bounds, relative to the source texture.
* @param srcBounds The source bounds, relative to the source texture. If non-null,
* no pixels will be sampled outside of this rectangle.
@ -37,6 +38,7 @@ namespace SkGpuBlurUtils {
GrTexture* GaussianBlur(GrContext* context,
GrTexture* srcTexture,
bool canClobberSrc,
bool allowSRGBInputs,
const SkRect& dstBounds,
const SkRect* srcBounds,
float sigmaX,

View File

@ -68,11 +68,13 @@ sk_sp<SkSpecialImage> SkImageSource::onFilterImage(SkSpecialImage* source, const
offset->fX = offset->fY = 0;
return SkSpecialImage::MakeFromImage(source->internal_getProxy(),
SkIRect::MakeWH(fImage->width(), fImage->height()),
fImage);
fImage,
&source->props());
}
const SkIRect dstIRect = dstRect.roundOut();
// SRGBTODO: Propagate SkColorType?
const SkImageInfo info = SkImageInfo::MakeN32(dstIRect.width(), dstIRect.height(),
kPremul_SkAlphaType);

View File

@ -387,6 +387,7 @@ void SkLightingImageFilterInternal::drawRect(GrDrawContext* drawContext,
const SkIRect& bounds) const {
SkRect srcRect = dstRect.makeOffset(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y()));
GrPaint paint;
// SRGBTODO: AllowSRGBInputs?
GrFragmentProcessor* fp = this->getFragmentProcessor(src, matrix, srcBounds, boundaryMode);
paint.addColorFragmentProcessor(fp)->unref();
paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);

View File

@ -370,6 +370,7 @@ static void apply_morphology_rect(GrDrawContext* drawContext,
float bounds[2],
Gr1DKernelEffect::Direction direction) {
GrPaint paint;
// SRGBTODO: AllowSRGBInputs?
paint.addColorFragmentProcessor(GrMorphologyEffect::Create(texture,
direction,
radius,
@ -389,6 +390,7 @@ static void apply_morphology_rect_no_bounds(GrDrawContext* drawContext,
GrMorphologyEffect::MorphologyType morphType,
Gr1DKernelEffect::Direction direction) {
GrPaint paint;
// SRGBTODO: AllowSRGBInputs?
paint.addColorFragmentProcessor(GrMorphologyEffect::Create(texture,
direction,
radius,
@ -511,7 +513,7 @@ static sk_sp<SkSpecialImage> apply_morphology(SkSpecialImage* input,
return SkSpecialImage::MakeFromGpu(input->internal_getProxy(),
SkIRect::MakeWH(rect.width(), rect.height()),
kNeedNewImageUniqueID_SpecialImage,
srcTexture);
srcTexture, &input->props());
}
#endif
@ -619,5 +621,5 @@ sk_sp<SkSpecialImage> SkMorphologyImageFilter::onFilterImage(SkSpecialImage* sou
return SkSpecialImage::MakeFromRaster(source->internal_getProxy(),
SkIRect::MakeWH(bounds.width(), bounds.height()),
dst);
dst, &source->props());
}

View File

@ -174,6 +174,7 @@ bool SkXfermodeImageFilter::filterImageGPUDeprecated(Proxy* proxy,
}
GrPaint paint;
// SRGBTODO: AllowSRGBInputs?
SkAutoTUnref<const GrFragmentProcessor> bgFP;
if (backgroundTex) {

View File

@ -335,7 +335,8 @@ void GrBlurUtils::drawPathWithMaskFilter(GrContext* context,
}
GrPaint grPaint;
if (!SkPaintToGrPaint(context, paint, viewMatrix, &grPaint)) {
if (!SkPaintToGrPaint(context, paint, viewMatrix, drawContext->allowSRGBInputs(),
&grPaint)) {
return;
}

View File

@ -366,6 +366,8 @@ bool GrContext::writeSurfacePixels(GrSurface* surface,
if (!drawContext) {
return false;
}
// SRGBTODO: AllowSRGBInputs? (We could force it on here, so we don't need the
// per-texture override in config conversion effect?)
GrPaint paint;
paint.addColorFragmentProcessor(fp);
paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
@ -476,6 +478,8 @@ bool GrContext::readSurfacePixels(GrSurface* src,
GrConfigConversionEffect::kNone_PMConversion, textureMatrix));
}
if (fp) {
// SRGBTODO: AllowSRGBInputs? (We could force it on here, so we don't need the
// per-texture override in config conversion effect?)
GrPaint paint;
paint.addColorFragmentProcessor(fp);
paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);

View File

@ -306,7 +306,8 @@ void GrLayerHoister::FilterLayer(GrContext* context,
const SkIRect subset = SkIRect::MakeWH(layer->texture()->width(), layer->texture()->height());
sk_sp<SkSpecialImage> img(SkSpecialImage::MakeFromGpu(&proxy, subset,
kNeedNewImageUniqueID_SpecialImage,
layer->texture()));
layer->texture(),
&device->surfaceProps()));
SkIPoint offset = SkIPoint::Make(0, 0);
sk_sp<SkSpecialImage> result(layer->filter()->filterImage(img.get(),

View File

@ -15,6 +15,7 @@
GrPaint::GrPaint()
: fAntiAlias(false)
, fDisableOutputConversionToSRGB(false)
, fAllowSRGBInputs(false)
, fColor(GrColor_WHITE) {}
void GrPaint::setCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage) {

View File

@ -84,6 +84,9 @@ GrPipeline* GrPipeline::CreateAt(void* memory, const CreateArgs& args,
if (builder.getDisableOutputConversionToSRGB()) {
pipeline->fFlags |= kDisableOutputConversionToSRGB_Flag;
}
if (builder.getAllowSRGBInputs()) {
pipeline->fFlags |= kAllowSRGBInputs_Flag;
}
int firstColorProcessorIdx = args.fOpts.fColorPOI.firstEffectiveProcessorIndex();

View File

@ -148,6 +148,9 @@ public:
bool getDisableOutputConversionToSRGB() const {
return SkToBool(fFlags & kDisableOutputConversionToSRGB_Flag);
}
bool getAllowSRGBInputs() const {
return SkToBool(fFlags & kAllowSRGBInputs_Flag);
}
GrXferBarrierType xferBarrierType(const GrCaps& caps) const {
return this->getXferProcessor().xferBarrierType(fRenderTarget.get(), caps);
@ -190,6 +193,7 @@ private:
kHWAA_Flag = 0x1,
kSnapVertices_Flag = 0x2,
kDisableOutputConversionToSRGB_Flag = 0x4,
kAllowSRGBInputs_Flag = 0x8,
};
typedef GrPendingIOResource<GrRenderTarget, kWrite_GrIOType> RenderTarget;

View File

@ -46,6 +46,8 @@ GrPipelineBuilder::GrPipelineBuilder(const GrPaint& paint, GrRenderTarget* rt, c
rt->isUnifiedMultisampled() && paint.isAntiAlias());
this->setState(GrPipelineBuilder::kDisableOutputConversionToSRGB_Flag,
paint.getDisableOutputConversionToSRGB());
this->setState(GrPipelineBuilder::kAllowSRGBInputs_Flag,
paint.getAllowSRGBInputs());
}
//////////////////////////////////////////////////////////////////////////////s

View File

@ -288,7 +288,12 @@ public:
*/
kDisableOutputConversionToSRGB_Flag = 0x04,
kLast_Flag = kDisableOutputConversionToSRGB_Flag,
/**
* Allow sRGB -> linear conversion when reading from sRGB inputs.
*/
kAllowSRGBInputs_Flag = 0x08,
kLast_Flag = kAllowSRGBInputs_Flag,
};
bool isHWAntialias() const { return SkToBool(fFlags & kHWAntialias_Flag); }
@ -296,6 +301,8 @@ public:
return SkToBool(fFlags & kSnapVerticesToPixelCenters_Flag); }
bool getDisableOutputConversionToSRGB() const {
return SkToBool(fFlags & kDisableOutputConversionToSRGB_Flag); }
bool getAllowSRGBInputs() const {
return SkToBool(fFlags & kAllowSRGBInputs_Flag); }
/**
* Enable render state settings.

View File

@ -396,7 +396,8 @@ void SkGpuDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawPaint", fContext);
GrPaint grPaint;
if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix,
this->surfaceProps().allowSRGBInputs(), &grPaint)) {
return;
}
@ -446,7 +447,8 @@ void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
if (paint.getPathEffect() && 2 == count && SkCanvas::kLines_PointMode == mode) {
GrStrokeInfo strokeInfo(paint, SkPaint::kStroke_Style);
GrPaint grPaint;
if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix,
this->surfaceProps().allowSRGBInputs(), &grPaint)) {
return;
}
SkPath path;
@ -466,7 +468,8 @@ void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
}
GrPaint grPaint;
if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix,
this->surfaceProps().allowSRGBInputs(), &grPaint)) {
return;
}
@ -518,7 +521,8 @@ void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect, const SkPaint
}
GrPaint grPaint;
if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix,
this->surfaceProps().allowSRGBInputs(), &grPaint)) {
return;
}
@ -536,7 +540,8 @@ void SkGpuDevice::drawRRect(const SkDraw& draw, const SkRRect& rect,
CHECK_SHOULD_DRAW(draw);
GrPaint grPaint;
if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix,
this->surfaceProps().allowSRGBInputs(), &grPaint)) {
return;
}
@ -611,7 +616,8 @@ void SkGpuDevice::drawDRRect(const SkDraw& draw, const SkRRect& outer,
if (stroke.isFillStyle() && !paint.getMaskFilter() && !paint.getPathEffect()) {
GrPaint grPaint;
if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix,
this->surfaceProps().allowSRGBInputs(), &grPaint)) {
return;
}
@ -655,7 +661,8 @@ void SkGpuDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint
}
GrPaint grPaint;
if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix,
this->surfaceProps().allowSRGBInputs(), &grPaint)) {
return;
}
@ -1139,7 +1146,8 @@ void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap,
GrPaint grPaint;
if (!SkPaintToGrPaintWithTexture(this->context(), paint, viewMatrix, fp,
kAlpha_8_SkColorType == bitmap.colorType(), &grPaint)) {
kAlpha_8_SkColorType == bitmap.colorType(),
this->surfaceProps().allowSRGBInputs(), &grPaint)) {
return;
}
@ -1233,7 +1241,8 @@ void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
} else {
fp.reset(GrFragmentProcessor::MulOutputByInputAlpha(fp));
}
if (!SkPaintToGrPaintReplaceShader(this->context(), paint, fp, &grPaint)) {
if (!SkPaintToGrPaintReplaceShader(this->context(), paint, fp,
this->surfaceProps().allowSRGBInputs(), &grPaint)) {
return;
}
@ -1393,7 +1402,8 @@ void SkGpuDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
fp.reset(GrFragmentProcessor::MulOutputByInputAlpha(fp));
}
if (!SkPaintToGrPaintReplaceShader(this->context(), paint, fp, &grPaint)) {
if (!SkPaintToGrPaintReplaceShader(this->context(), paint, fp,
this->surfaceProps().allowSRGBInputs(), &grPaint)) {
return;
}
@ -1532,7 +1542,8 @@ void SkGpuDevice::drawProducerNine(const SkDraw& draw, GrTextureProducer* produc
&kMode));
GrPaint grPaint;
if (!SkPaintToGrPaintWithTexture(this->context(), paint, *draw.fMatrix, fp,
producer->isAlphaOnly(), &grPaint)) {
producer->isAlphaOnly(),
this->surfaceProps().allowSRGBInputs(), &grPaint)) {
return;
}
@ -1599,7 +1610,8 @@ void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
GrPaint grPaint;
// we ignore the shader if texs is null.
if (!SkPaintToGrPaintNoShader(this->context(), copy, &grPaint)) {
if (!SkPaintToGrPaintNoShader(this->context(), copy,
this->surfaceProps().allowSRGBInputs(), &grPaint)) {
return;
}
@ -1671,12 +1683,14 @@ void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
colorMode = SkXfermode::kModulate_Mode;
}
if (!SkPaintToGrPaintWithXfermode(this->context(), paint, *draw.fMatrix, colorMode,
false, &grPaint)) {
false, this->surfaceProps().allowSRGBInputs(),
&grPaint)) {
return;
}
} else {
// We have a shader, but no colors to blend it against.
if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix,
this->surfaceProps().allowSRGBInputs(), &grPaint)) {
return;
}
}
@ -1684,12 +1698,15 @@ void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
if (colors) {
// We have colors, but either have no shader or no texture coords (which implies that
// we should ignore the shader).
if (!SkPaintToGrPaintWithPrimitiveColor(this->context(), paint, &grPaint)) {
if (!SkPaintToGrPaintWithPrimitiveColor(this->context(), paint,
this->surfaceProps().allowSRGBInputs(),
&grPaint)) {
return;
}
} else {
// No colors and no shaders. Just draw with the paint color.
if (!SkPaintToGrPaintNoShader(this->context(), paint, &grPaint)) {
if (!SkPaintToGrPaintNoShader(this->context(), paint,
this->surfaceProps().allowSRGBInputs(), &grPaint)) {
return;
}
}
@ -1727,11 +1744,12 @@ void SkGpuDevice::drawAtlas(const SkDraw& draw, const SkImage* atlas, const SkRS
GrPaint grPaint;
if (colors) {
if (!SkPaintToGrPaintWithXfermode(this->context(), p, *draw.fMatrix, mode, true,
&grPaint)) {
this->surfaceProps().allowSRGBInputs(), &grPaint)) {
return;
}
} else {
if (!SkPaintToGrPaint(this->context(), p, *draw.fMatrix, &grPaint)) {
if (!SkPaintToGrPaint(this->context(), p, *draw.fMatrix,
this->surfaceProps().allowSRGBInputs(), &grPaint)) {
return;
}
}
@ -1750,7 +1768,8 @@ void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawText", fContext);
GrPaint grPaint;
if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix,
this->surfaceProps().allowSRGBInputs(), &grPaint)) {
return;
}
@ -1768,7 +1787,8 @@ void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text, size_t byteL
CHECK_SHOULD_DRAW(draw);
GrPaint grPaint;
if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix,
this->surfaceProps().allowSRGBInputs(), &grPaint)) {
return;
}

View File

@ -206,7 +206,7 @@ void SkGpuDevice::drawTextureProducerImpl(GrTextureProducer* producer,
GrPaint grPaint;
if (!SkPaintToGrPaintWithTexture(fContext, paint, viewMatrix, fp, producer->isAlphaOnly(),
&grPaint)) {
this->surfaceProps().allowSRGBInputs(), &grPaint)) {
return;
}

View File

@ -495,8 +495,10 @@ static inline bool skpaint_to_grpaint_impl(GrContext* context,
const GrFragmentProcessor** shaderProcessor,
SkXfermode::Mode* primColorMode,
bool primitiveIsSrc,
bool allowSRGBInputs,
GrPaint* grPaint) {
grPaint->setAntiAlias(skPaint.isAntiAlias());
grPaint->setAllowSRGBInputs(allowSRGBInputs);
// Setup the initial color considering the shader, the SkPaint color, and the presence or not
// of per-vertex colors.
@ -623,31 +625,34 @@ static inline bool skpaint_to_grpaint_impl(GrContext* context,
}
bool SkPaintToGrPaint(GrContext* context, const SkPaint& skPaint, const SkMatrix& viewM,
GrPaint* grPaint) {
return skpaint_to_grpaint_impl(context, skPaint, viewM, nullptr, nullptr, false, grPaint);
bool allowSRGBInputs, GrPaint* grPaint) {
return skpaint_to_grpaint_impl(context, skPaint, viewM, nullptr, nullptr, false,
allowSRGBInputs, grPaint);
}
/** Replaces the SkShader (if any) on skPaint with the passed in GrFragmentProcessor. */
bool SkPaintToGrPaintReplaceShader(GrContext* context,
const SkPaint& skPaint,
const GrFragmentProcessor* shaderFP,
bool allowSRGBInputs,
GrPaint* grPaint) {
if (!shaderFP) {
return false;
}
return skpaint_to_grpaint_impl(context, skPaint, SkMatrix::I(), &shaderFP, nullptr, false,
grPaint);
allowSRGBInputs, grPaint);
}
/** Ignores the SkShader (if any) on skPaint. */
bool SkPaintToGrPaintNoShader(GrContext* context,
const SkPaint& skPaint,
bool allowSRGBInputs,
GrPaint* grPaint) {
// Use a ptr to a nullptr to to indicate that the SkShader is ignored and not replaced.
static const GrFragmentProcessor* kNullShaderFP = nullptr;
static const GrFragmentProcessor** kIgnoreShader = &kNullShaderFP;
return skpaint_to_grpaint_impl(context, skPaint, SkMatrix::I(), kIgnoreShader, nullptr, false,
grPaint);
allowSRGBInputs, grPaint);
}
/** Blends the SkPaint's shader (or color if no shader) with a per-primitive color which must
@ -657,9 +662,10 @@ bool SkPaintToGrPaintWithXfermode(GrContext* context,
const SkMatrix& viewM,
SkXfermode::Mode primColorMode,
bool primitiveIsSrc,
bool allowSRGBInputs,
GrPaint* grPaint) {
return skpaint_to_grpaint_impl(context, skPaint, viewM, nullptr, &primColorMode, primitiveIsSrc,
grPaint);
allowSRGBInputs, grPaint);
}
bool SkPaintToGrPaintWithTexture(GrContext* context,
@ -667,6 +673,7 @@ bool SkPaintToGrPaintWithTexture(GrContext* context,
const SkMatrix& viewM,
const GrFragmentProcessor* fp,
bool textureIsAlphaOnly,
bool allowSRGBInputs,
GrPaint* grPaint) {
SkAutoTUnref<const GrFragmentProcessor> shaderFP;
if (textureIsAlphaOnly) {
@ -687,7 +694,7 @@ bool SkPaintToGrPaintWithTexture(GrContext* context,
shaderFP.reset(GrFragmentProcessor::MulOutputByInputAlpha(fp));
}
return SkPaintToGrPaintReplaceShader(context, paint, shaderFP.get(), grPaint);
return SkPaintToGrPaintReplaceShader(context, paint, shaderFP.get(), allowSRGBInputs, grPaint);
}

View File

@ -48,11 +48,13 @@ void GrInstallBitmapUniqueKeyInvalidator(const GrUniqueKey& key, SkPixelRef* pix
bool SkPaintToGrPaint(GrContext*,
const SkPaint& skPaint,
const SkMatrix& viewM,
bool allowSRGBInputs,
GrPaint* grPaint);
/** Same as above but ignores the SkShader (if any) on skPaint. */
bool SkPaintToGrPaintNoShader(GrContext* context,
const SkPaint& skPaint,
bool allowSRGBInputs,
GrPaint* grPaint);
/** Replaces the SkShader (if any) on skPaint with the passed in GrFragmentProcessor. The processor
@ -61,6 +63,7 @@ bool SkPaintToGrPaintNoShader(GrContext* context,
bool SkPaintToGrPaintReplaceShader(GrContext*,
const SkPaint& skPaint,
const GrFragmentProcessor* shaderFP,
bool allowSRGBInputs,
GrPaint* grPaint);
/** Blends the SkPaint's shader (or color if no shader) with the color which specified via a
@ -72,6 +75,7 @@ bool SkPaintToGrPaintWithXfermode(GrContext* context,
const SkMatrix& viewM,
SkXfermode::Mode primColorMode,
bool primitiveIsSrc,
bool allowSRGBInputs,
GrPaint* grPaint);
/** This is used when there is a primitive color, but the shader should be ignored. Currently,
@ -79,9 +83,9 @@ bool SkPaintToGrPaintWithXfermode(GrContext* context,
unpremultiplied so that interpolation is done in unpremul space. The paint's alpha will be
applied to the primitive color after interpolation. */
inline bool SkPaintToGrPaintWithPrimitiveColor(GrContext* context, const SkPaint& skPaint,
GrPaint* grPaint) {
bool allowSRGBInputs, GrPaint* grPaint) {
return SkPaintToGrPaintWithXfermode(context, skPaint, SkMatrix::I(), SkXfermode::kDst_Mode,
false, grPaint);
false, allowSRGBInputs, grPaint);
}
/** This is used when there may or may not be a shader, and the caller wants to plugin a texture
@ -91,6 +95,7 @@ bool SkPaintToGrPaintWithTexture(GrContext* context,
const SkMatrix& viewM,
const GrFragmentProcessor* fp,
bool textureIsAlphaOnly,
bool allowSRGBInputs,
GrPaint* grPaint);
//////////////////////////////////////////////////////////////////////////////

View File

@ -2051,15 +2051,13 @@ bool GrGLGpu::flushGLState(const GrPipeline& pipeline, const GrPrimitiveProcesso
SkSTArray<8, const GrTextureAccess*> textureAccesses;
program->setData(primProc, pipeline, &textureAccesses);
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(pipeline.getRenderTarget());
bool allowSRGB = GrAllowSRGBForDestinationPixelConfig(glRT->config());
int numTextureAccesses = textureAccesses.count();
for (int i = 0; i < numTextureAccesses; i++) {
this->bindTexture(i, textureAccesses[i]->getParams(), allowSRGB,
this->bindTexture(i, textureAccesses[i]->getParams(), pipeline.getAllowSRGBInputs(),
static_cast<GrGLTexture*>(textureAccesses[i]->getTexture()));
}
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(pipeline.getRenderTarget());
this->flushStencil(pipeline.getStencil());
this->flushScissor(pipeline.getScissorState(), glRT->getViewport(), glRT->origin());
this->flushHWAAState(glRT, pipeline.isHWAntialiasState(), !pipeline.getStencil().isDisabled());

View File

@ -112,7 +112,7 @@ void GrAtlasTextContext::drawTextBlob(GrContext* context, GrDrawContext* dc,
// Though for the time being runs in the textblob can override the paint, they only touch font
// info.
GrPaint grPaint;
if (!SkPaintToGrPaint(context, skPaint, viewMatrix, &grPaint)) {
if (!SkPaintToGrPaint(context, skPaint, viewMatrix, props.allowSRGBInputs(), &grPaint)) {
return;
}
@ -382,7 +382,8 @@ DRAW_BATCH_TEST_DEFINE(TextBlobBatch) {
skPaint.setSubpixelText(random->nextBool());
GrPaint grPaint;
if (!SkPaintToGrPaint(context, skPaint, viewMatrix, &grPaint)) {
if (!SkPaintToGrPaint(context, skPaint, viewMatrix, gSurfaceProps.allowSRGBInputs(),
&grPaint)) {
SkFAIL("couldn't convert paint\n");
}

View File

@ -165,7 +165,7 @@ void GrStencilAndCoverTextContext::uncachedDrawTextBlob(GrContext* context,
runPaint.setFlags(GrTextUtils::FilterTextFlags(props, runPaint));
GrPaint grPaint;
if (!SkPaintToGrPaint(context, runPaint, viewMatrix, &grPaint)) {
if (!SkPaintToGrPaint(context, runPaint, viewMatrix, dc->allowSRGBInputs(), &grPaint)) {
return;
}
@ -220,7 +220,7 @@ void GrStencilAndCoverTextContext::drawTextBlob(GrContext* context, GrDrawContex
}
GrPaint paint;
if (!SkPaintToGrPaint(context, skPaint, viewMatrix, &paint)) {
if (!SkPaintToGrPaint(context, skPaint, viewMatrix, dc->allowSRGBInputs(), &paint)) {
return;
}

View File

@ -70,6 +70,13 @@ void SkWindow::resize(int width, int height) {
void SkWindow::setColorType(SkColorType ct, SkColorProfileType pt) {
const SkImageInfo& info = fBitmap.info();
this->resize(SkImageInfo::Make(info.width(), info.height(), ct, kPremul_SkAlphaType, pt));
// Set the global flag that enables or disables "legacy" mode, depending on our format.
// With sRGB 32-bit or linear FP 16, we turn on gamma-correct handling of inputs:
SkSurfaceProps props = this->getSurfaceProps();
uint32_t flags = (props.flags() & ~SkSurfaceProps::kAllowSRGBInputs_Flag) |
(SkColorAndProfileAreGammaCorrect(ct, pt) ? SkSurfaceProps::kAllowSRGBInputs_Flag : 0);
this->setSurfaceProps(SkSurfaceProps(flags, props.pixelGeometry()));
}
bool SkWindow::handleInval(const SkRect* localR) {
@ -333,9 +340,7 @@ GrRenderTarget* SkWindow::renderTarget(const AttachmentInfo& attachmentInfo,
//
// Also, we may not have real sRGB support (ANGLE, in particular), so check for
// that, and fall back to L32:
desc.fConfig = grContext->caps()->srgbSupport() &&
(info().profileType() == kSRGB_SkColorProfileType ||
info().colorType() == kRGBA_F16_SkColorType)
desc.fConfig = grContext->caps()->srgbSupport() && SkImageInfoIsGammaCorrect(info())
? kSkiaGamma8888_GrPixelConfig
: kSkia8888_GrPixelConfig;
desc.fOrigin = kBottomLeft_GrSurfaceOrigin;

View File

@ -155,7 +155,8 @@ void SkGpuDevice::drawTexture(GrTexture* tex, const SkRect& dst, const SkPaint&
GrPaint grPaint;
SkMatrix mat;
mat.reset();
if (!SkPaintToGrPaint(this->context(), paint, mat, &grPaint)) {
if (!SkPaintToGrPaint(this->context(), paint, mat,
this->surfaceProps().allowSRGBInputs(), &grPaint)) {
return;
}
SkMatrix textureMat;