skia2/gm/texturedomaineffect.cpp
brianosman 54f30c13fc Introduce GrColorSpaceXform, for gamut conversion on textures
GrTextureAccess optionally includes an instance, computed from the src
and dst color spaces. In all common cases (no color space for either src
or dst, or same color space for both), no object is allocated.

This change is orthogonal to my attempts to get color space attached to
render targets - regardless of how we choose to do that, this will give
us the source color space at all points where we are connecting src to
dst.

There are many dangling injection points where I've been inserting
nullptr, but I have a record of all of them. Additionally, there are now
three places (the most common simple paths for bitmap/image rendering)
where things are plumbed enough that I expect to have access to the dst
color space (all marked with XFORMTODO).

In addition to getting the dst color space, I need to inject shader code
and uniform uploading for appendTextureLookup and friends.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2154753003

Review-Url: https://codereview.chromium.org/2154753003
2016-07-18 10:53:52 -07:00

158 lines
5.9 KiB
C++

/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
// This test only works with the GPU backend.
#include "gm.h"
#if SK_SUPPORT_GPU
#include "GrDrawContextPriv.h"
#include "GrContext.h"
#include "SkBitmap.h"
#include "SkGr.h"
#include "SkGradientShader.h"
#include "batches/GrDrawBatch.h"
#include "batches/GrRectBatchFactory.h"
#include "effects/GrTextureDomain.h"
namespace skiagm {
/**
* This GM directly exercises GrTextureDomainEffect.
*/
class TextureDomainEffect : public GM {
public:
TextureDomainEffect() {
this->setBGColor(0xFFFFFFFF);
}
protected:
SkString onShortName() override {
return SkString("texture_domain_effect");
}
SkISize onISize() override {
const SkScalar canvasWidth = kDrawPad +
(kTargetWidth + 2 * kDrawPad) * GrTextureDomain::kModeCount +
kTestPad * GrTextureDomain::kModeCount;
return SkISize::Make(SkScalarCeilToInt(canvasWidth), 800);
}
void onOnceBeforeDraw() override {
fBmp.allocN32Pixels(kTargetWidth, kTargetHeight);
SkCanvas canvas(fBmp);
canvas.clear(0x00000000);
SkPaint paint;
SkColor colors1[] = { SK_ColorCYAN, SK_ColorLTGRAY, SK_ColorGRAY };
paint.setShader(SkGradientShader::MakeSweep(65.f, 75.f, colors1, nullptr,
SK_ARRAY_COUNT(colors1)));
canvas.drawOval(SkRect::MakeXYWH(-5.f, -5.f, fBmp.width() + 10.f, fBmp.height() + 10.f),
paint);
SkColor colors2[] = { SK_ColorMAGENTA, SK_ColorLTGRAY, SK_ColorYELLOW };
paint.setShader(SkGradientShader::MakeSweep(45.f, 55.f, colors2, nullptr,
SK_ARRAY_COUNT(colors2)));
paint.setXfermodeMode(SkXfermode::kDarken_Mode);
canvas.drawOval(SkRect::MakeXYWH(-5.f, -5.f, fBmp.width() + 10.f, fBmp.height() + 10.f),
paint);
SkColor colors3[] = { SK_ColorBLUE, SK_ColorLTGRAY, SK_ColorGREEN };
paint.setShader(SkGradientShader::MakeSweep(25.f, 35.f, colors3, nullptr,
SK_ARRAY_COUNT(colors3)));
paint.setXfermodeMode(SkXfermode::kLighten_Mode);
canvas.drawOval(SkRect::MakeXYWH(-5.f, -5.f, fBmp.width() + 10.f, fBmp.height() + 10.f),
paint);
}
void onDraw(SkCanvas* canvas) override {
GrDrawContext* drawContext = canvas->internal_private_accessTopLayerDrawContext();
if (!drawContext) {
skiagm::GM::DrawGpuOnlyMessage(canvas);
return;
}
GrContext* context = canvas->getGrContext();
if (!context) {
return;
}
SkAutoTUnref<GrTexture> texture(GrRefCachedBitmapTexture(context, fBmp,
GrTextureParams::ClampNoFilter(),
SkSourceGammaTreatment::kRespect));
if (!texture) {
return;
}
SkTArray<SkMatrix> textureMatrices;
textureMatrices.push_back().setIDiv(texture->width(), texture->height());
textureMatrices.push_back() = textureMatrices[0];
textureMatrices.back().postScale(1.5f, 0.85f);
textureMatrices.push_back() = textureMatrices[0];
textureMatrices.back().preRotate(45.f, texture->width() / 2.f, texture->height() / 2.f);
const SkIRect texelDomains[] = {
fBmp.bounds(),
SkIRect::MakeXYWH(fBmp.width() / 4,
fBmp.height() / 4,
fBmp.width() / 2,
fBmp.height() / 2),
};
SkRect renderRect = SkRect::Make(fBmp.bounds());
renderRect.outset(kDrawPad, kDrawPad);
SkScalar y = kDrawPad + kTestPad;
for (int tm = 0; tm < textureMatrices.count(); ++tm) {
for (size_t d = 0; d < SK_ARRAY_COUNT(texelDomains); ++d) {
SkScalar x = kDrawPad + kTestPad;
for (int m = 0; m < GrTextureDomain::kModeCount; ++m) {
GrTextureDomain::Mode mode = (GrTextureDomain::Mode) m;
GrPaint grPaint;
grPaint.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::kSrc_Mode));
sk_sp<GrFragmentProcessor> fp(
GrTextureDomainEffect::Make(texture, nullptr, textureMatrices[tm],
GrTextureDomain::MakeTexelDomain(texture,
texelDomains[d]),
mode, GrTextureParams::kNone_FilterMode));
if (!fp) {
continue;
}
const SkMatrix viewMatrix = SkMatrix::MakeTrans(x, y);
grPaint.addColorFragmentProcessor(std::move(fp));
SkAutoTUnref<GrDrawBatch> batch(
GrRectBatchFactory::CreateNonAAFill(GrColor_WHITE, viewMatrix,
renderRect, nullptr, nullptr));
drawContext->drawContextPriv().testingOnly_drawBatch(grPaint, batch);
x += renderRect.width() + kTestPad;
}
y += renderRect.height() + kTestPad;
}
}
}
private:
static const SkScalar kDrawPad;
static const SkScalar kTestPad;
static const int kTargetWidth = 100;
static const int kTargetHeight = 100;
SkBitmap fBmp;
typedef GM INHERITED;
};
// Windows builds did not like SkScalar initialization in class :(
const SkScalar TextureDomainEffect::kDrawPad = 10.f;
const SkScalar TextureDomainEffect::kTestPad = 10.f;
DEF_GM(return new TextureDomainEffect;)
}
#endif