diff --git a/gm/imagemagnifier.cpp b/gm/imagemagnifier.cpp index 88a6d10d96..888bb5d9ab 100644 --- a/gm/imagemagnifier.cpp +++ b/gm/imagemagnifier.cpp @@ -8,6 +8,7 @@ #include "gm.h" #include "SkImageSource.h" #include "SkMagnifierImageFilter.h" +#include "SkPixelRef.h" #include "SkRandom.h" #include "SkSurface.h" @@ -43,23 +44,25 @@ DEF_SIMPLE_GM_BG(imagemagnifier, canvas, WIDTH, HEIGHT, SK_ColorBLACK) { #define WIDTH_HEIGHT 256 static sk_sp make_img() { - const SkImageInfo info = SkImageInfo::MakeN32Premul(WIDTH_HEIGHT, WIDTH_HEIGHT); + SkBitmap bitmap; + bitmap.allocN32Pixels(WIDTH_HEIGHT, WIDTH_HEIGHT); + SkCanvas canvas(bitmap); - sk_sp surf(SkSurface::MakeRaster(info)); - - SkCanvas* canvas = surf->getCanvas(); - - canvas->clear(0x0); + canvas.clear(0x0); SkPaint paint; paint.setColor(SK_ColorBLUE); for (float pos = 0; pos < WIDTH_HEIGHT; pos += 16) { - canvas->drawLine(0, pos, SkIntToScalar(WIDTH_HEIGHT), pos, paint); - canvas->drawLine(pos, 0, pos, SkIntToScalar(WIDTH_HEIGHT), paint); + canvas.drawLine(0, pos, SkIntToScalar(WIDTH_HEIGHT), pos, paint); + canvas.drawLine(pos, 0, pos, SkIntToScalar(WIDTH_HEIGHT), paint); } - return surf->makeImageSnapshot(); + SkBitmap result; + result.setInfo(SkImageInfo::MakeS32(WIDTH_HEIGHT, WIDTH_HEIGHT, kPremul_SkAlphaType)); + result.setPixelRef(sk_ref_sp(bitmap.pixelRef()), 0, 0); + + return SkImage::MakeFromBitmap(result); } DEF_SIMPLE_GM_BG(imagemagnifier_cropped, canvas, WIDTH_HEIGHT, WIDTH_HEIGHT, SK_ColorBLACK) { diff --git a/src/effects/SkMagnifierImageFilter.cpp b/src/effects/SkMagnifierImageFilter.cpp index 916bd950a6..2b045322eb 100644 --- a/src/effects/SkMagnifierImageFilter.cpp +++ b/src/effects/SkMagnifierImageFilter.cpp @@ -19,6 +19,7 @@ #include "GrContext.h" #include "GrInvariantOutput.h" #include "effects/GrSingleTextureEffect.h" +#include "glsl/GrGLSLColorSpaceXformHelper.h" #include "glsl/GrGLSLFragmentProcessor.h" #include "glsl/GrGLSLFragmentShaderBuilder.h" #include "glsl/GrGLSLProgramDataManager.h" @@ -29,6 +30,7 @@ class GrMagnifierEffect : public GrSingleTextureEffect { public: static sk_sp Make(GrTexture* texture, + sk_sp colorSpaceXform, const SkRect& bounds, float xOffset, float yOffset, @@ -36,8 +38,8 @@ public: float yInvZoom, float xInvInset, float yInvInset) { - return sk_sp(new GrMagnifierEffect(texture, bounds, - xOffset, yOffset, + return sk_sp(new GrMagnifierEffect(texture, std::move(colorSpaceXform), + bounds, xOffset, yOffset, xInvZoom, yInvZoom, xInvInset, yInvInset)); } @@ -61,6 +63,7 @@ public: private: GrMagnifierEffect(GrTexture* texture, + sk_sp colorSpaceXform, const SkRect& bounds, float xOffset, float yOffset, @@ -68,7 +71,8 @@ private: float yInvZoom, float xInvInset, float yInvInset) - : INHERITED(texture, nullptr, GrCoordTransform::MakeDivByTextureWHMatrix(texture)) + : INHERITED(texture, std::move(colorSpaceXform), + GrCoordTransform::MakeDivByTextureWHMatrix(texture)) , fBounds(bounds) , fXOffset(xOffset) , fYOffset(yOffset) @@ -107,6 +111,12 @@ class GrGLMagnifierEffect : public GrGLSLFragmentProcessor { public: void emitCode(EmitArgs&) override; + static inline void GenKey(const GrProcessor& effect, const GrShaderCaps&, + GrProcessorKeyBuilder* b) { + const GrMagnifierEffect& zoom = effect.cast(); + b->add32(GrColorSpaceXform::XformKey(zoom.colorSpaceXform())); + } + protected: void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override; @@ -115,6 +125,7 @@ private: UniformHandle fInvZoomVar; UniformHandle fInvInsetVar; UniformHandle fBoundsVar; + UniformHandle fColorSpaceXformVar; typedef GrGLSLFragmentProcessor INHERITED; }; @@ -134,6 +145,10 @@ void GrGLMagnifierEffect::emitCode(EmitArgs& args) { kVec4f_GrSLType, kDefault_GrSLPrecision, "Bounds"); + const GrMagnifierEffect& zoom = args.fFp.cast(); + GrGLSLColorSpaceXformHelper colorSpaceHelper(uniformHandler, zoom.colorSpaceXform(), + &fColorSpaceXformVar); + GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]); fragBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str()); @@ -160,7 +175,8 @@ void GrGLMagnifierEffect::emitCode(EmitArgs& args) { fragBuilder->codeAppend("\t\tvec2 mix_coord = mix(coord, zoom_coord, weight);\n"); fragBuilder->codeAppend("\t\tvec4 output_color = "); - fragBuilder->appendTextureLookup(args.fTexSamplers[0], "mix_coord"); + fragBuilder->appendTextureLookup(args.fTexSamplers[0], "mix_coord", kVec2f_GrSLType, + &colorSpaceHelper); fragBuilder->codeAppend(";\n"); fragBuilder->codeAppendf("\t\t%s = output_color;", args.fOutputColor); @@ -177,6 +193,9 @@ void GrGLMagnifierEffect::onSetData(const GrGLSLProgramDataManager& pdman, pdman.set2f(fInvInsetVar, zoom.xInvInset(), zoom.yInvInset()); pdman.set4f(fBoundsVar, zoom.bounds().x(), zoom.bounds().y(), zoom.bounds().width(), zoom.bounds().height()); + if (SkToBool(zoom.colorSpaceXform())) { + pdman.setSkMatrix44(fColorSpaceXformVar, zoom.colorSpaceXform()->srcToDst()); + } } ///////////////////////////////////////////////////////////////////// @@ -202,9 +221,11 @@ sk_sp GrMagnifierEffect::TestCreate(GrProcessorTestData* d) uint32_t x = d->fRandom->nextULessThan(kMaxWidth - width); uint32_t y = d->fRandom->nextULessThan(kMaxHeight - height); uint32_t inset = d->fRandom->nextULessThan(kMaxInset); + auto colorSpaceXform = GrTest::TestColorXform(d->fRandom); sk_sp effect(GrMagnifierEffect::Make( texture, + std::move(colorSpaceXform), SkRect::MakeWH(SkIntToScalar(kMaxWidth), SkIntToScalar(kMaxHeight)), (float) width / texture->width(), (float) height / texture->height(), @@ -323,9 +344,13 @@ sk_sp SkMagnifierImageFilter::onFilterImage(SkSpecialImage* sour SkIntToScalar(boundsY) / inputTexture->height(), SkIntToScalar(inputTexture->width()) / bounds.width(), SkIntToScalar(inputTexture->height()) / bounds.height()); - // SRGBTODO: Handle sRGB here + + SkColorSpace* dstColorSpace = ctx.outputProperties().colorSpace(); + sk_sp colorSpaceXform = GrColorSpaceXform::Make(input->getColorSpace(), + dstColorSpace); sk_sp fp(GrMagnifierEffect::Make( inputTexture.get(), + std::move(colorSpaceXform), effectBounds, fSrcRect.x() / inputTexture->width(), yOffset / inputTexture->height(),