Separate MIP filtering from min/mag filtering.
Does not add kNearest as a mip map mode yet. Bug: skia:10344 Change-Id: Ida80cbf19e2b1eed5209d0680837fb45e54b4261 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/303481 Commit-Queue: Brian Salomon <bsalomon@google.com> Reviewed-by: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Greg Daniel <egdaniel@google.com>
This commit is contained in:
parent
40ad5fd50a
commit
e69b9efcb3
@ -254,10 +254,19 @@ void ClockwiseGM::onDraw(GrRecordingContext* ctx, GrRenderTargetContext* rtc, Sk
|
|||||||
topLeftRTC->clear(SK_PMColor4fTRANSPARENT);
|
topLeftRTC->clear(SK_PMColor4fTRANSPARENT);
|
||||||
topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, false, 0));
|
topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, false, 0));
|
||||||
topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, true, 100));
|
topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, true, 100));
|
||||||
rtc->drawTexture(nullptr, topLeftRTC->readSurfaceView(), rtc->colorInfo().alphaType(),
|
rtc->drawTexture(nullptr,
|
||||||
GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver, SK_PMColor4fWHITE,
|
topLeftRTC->readSurfaceView(),
|
||||||
{0, 0, 100, 200}, {100, 0, 200, 200}, GrAA::kNo, GrQuadAAFlags::kNone,
|
rtc->colorInfo().alphaType(),
|
||||||
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, SkMatrix::I(),
|
GrSamplerState::Filter::kNearest,
|
||||||
|
GrSamplerState::MipmapMode::kNone,
|
||||||
|
SkBlendMode::kSrcOver,
|
||||||
|
SK_PMColor4fWHITE,
|
||||||
|
{0, 0, 100, 200},
|
||||||
|
{100, 0, 200, 200},
|
||||||
|
GrAA::kNo,
|
||||||
|
GrQuadAAFlags::kNone,
|
||||||
|
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint,
|
||||||
|
SkMatrix::I(),
|
||||||
nullptr);
|
nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,10 +278,19 @@ void ClockwiseGM::onDraw(GrRecordingContext* ctx, GrRenderTargetContext* rtc, Sk
|
|||||||
topLeftRTC->clear(SK_PMColor4fTRANSPARENT);
|
topLeftRTC->clear(SK_PMColor4fTRANSPARENT);
|
||||||
topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, false, 0));
|
topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, false, 0));
|
||||||
topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, true, 100));
|
topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, true, 100));
|
||||||
rtc->drawTexture(nullptr, topLeftRTC->readSurfaceView(), rtc->colorInfo().alphaType(),
|
rtc->drawTexture(nullptr,
|
||||||
GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver, SK_PMColor4fWHITE,
|
topLeftRTC->readSurfaceView(),
|
||||||
{0, 0, 100, 200}, {200, 0, 300, 200}, GrAA::kNo, GrQuadAAFlags::kNone,
|
rtc->colorInfo().alphaType(),
|
||||||
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, SkMatrix::I(),
|
GrSamplerState::Filter::kNearest,
|
||||||
|
GrSamplerState::MipmapMode::kNone,
|
||||||
|
SkBlendMode::kSrcOver,
|
||||||
|
SK_PMColor4fWHITE,
|
||||||
|
{0, 0, 100, 200},
|
||||||
|
{200, 0, 300, 200},
|
||||||
|
GrAA::kNo,
|
||||||
|
GrQuadAAFlags::kNone,
|
||||||
|
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint,
|
||||||
|
SkMatrix::I(),
|
||||||
nullptr);
|
nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -366,11 +366,19 @@ DrawResult SampleLocationsGM::onDraw(GrRecordingContext* ctx, GrRenderTargetCont
|
|||||||
SkMatrix::I(), SkRect::MakeWH(200, 200));
|
SkMatrix::I(), SkRect::MakeWH(200, 200));
|
||||||
|
|
||||||
// Copy offscreen texture to canvas.
|
// Copy offscreen texture to canvas.
|
||||||
rtc->drawTexture(nullptr, offscreenRTC->readSurfaceView(),
|
rtc->drawTexture(nullptr,
|
||||||
|
offscreenRTC->readSurfaceView(),
|
||||||
offscreenRTC->colorInfo().alphaType(),
|
offscreenRTC->colorInfo().alphaType(),
|
||||||
GrSamplerState::Filter::kNearest, SkBlendMode::kSrc, SK_PMColor4fWHITE,
|
GrSamplerState::Filter::kNearest,
|
||||||
{0,0,200,200}, {0,0,200,200}, GrAA::kNo, GrQuadAAFlags::kNone,
|
GrSamplerState::MipmapMode::kNone,
|
||||||
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, SkMatrix::I(),
|
SkBlendMode::kSrc,
|
||||||
|
SK_PMColor4fWHITE,
|
||||||
|
{0, 0, 200, 200},
|
||||||
|
{0, 0, 200, 200},
|
||||||
|
GrAA::kNo,
|
||||||
|
GrQuadAAFlags::kNone,
|
||||||
|
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint,
|
||||||
|
SkMatrix::I(),
|
||||||
nullptr);
|
nullptr);
|
||||||
|
|
||||||
return skiagm::DrawResult::kOk;
|
return skiagm::DrawResult::kOk;
|
||||||
|
@ -33,28 +33,37 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
using MipmapMode = GrSamplerState::MipmapMode;
|
||||||
|
using Filter = GrSamplerState::Filter;
|
||||||
|
using Wrap = GrSamplerState::WrapMode;
|
||||||
|
|
||||||
namespace skiagm {
|
namespace skiagm {
|
||||||
/**
|
/**
|
||||||
* This GM directly exercises GrTextureEffect::MakeTexelSubset.
|
* This GM directly exercises GrTextureEffect::MakeTexelSubset.
|
||||||
*/
|
*/
|
||||||
class TexelSubset : public GpuGM {
|
class TexelSubset : public GpuGM {
|
||||||
public:
|
public:
|
||||||
TexelSubset(GrSamplerState::Filter filter, bool upscale) : fFilter(filter), fUpscale(upscale) {
|
TexelSubset(Filter filter, MipmapMode mm, bool upscale)
|
||||||
|
: fFilter(filter), fMipmapMode(mm), fUpscale(upscale) {
|
||||||
this->setBGColor(0xFFFFFFFF);
|
this->setBGColor(0xFFFFFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SkString onShortName() override {
|
SkString onShortName() override {
|
||||||
SkString name("texel_subset");
|
SkString name("texel_subset");
|
||||||
|
switch (fMipmapMode) {
|
||||||
|
case MipmapMode::kNone:
|
||||||
|
break;
|
||||||
|
case MipmapMode::kLinear:
|
||||||
|
name.append("_linear_mipmap");
|
||||||
|
break;
|
||||||
|
}
|
||||||
switch (fFilter) {
|
switch (fFilter) {
|
||||||
case GrSamplerState::Filter::kNearest:
|
case Filter::kNearest:
|
||||||
name.append("_nearest");
|
name.append("_nearest");
|
||||||
break;
|
break;
|
||||||
case GrSamplerState::Filter::kLinear:
|
case Filter::kLinear:
|
||||||
name.append("_bilerp");
|
name.append("_linear");
|
||||||
break;
|
|
||||||
case GrSamplerState::Filter::kMipMap:
|
|
||||||
name.append("_mip_map");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
name.append(fUpscale ? "_up" : "_down");
|
name.append(fUpscale ? "_up" : "_down");
|
||||||
@ -77,11 +86,13 @@ protected:
|
|||||||
|
|
||||||
DrawResult onDraw(GrRecordingContext* context, GrRenderTargetContext* renderTargetContext,
|
DrawResult onDraw(GrRecordingContext* context, GrRenderTargetContext* renderTargetContext,
|
||||||
SkCanvas* canvas, SkString* errorMsg) override {
|
SkCanvas* canvas, SkString* errorMsg) override {
|
||||||
GrMipmapped mipMapped = fFilter == GrSamplerState::Filter::kMipMap &&
|
GrMipmapped mipmapped = (fMipmapMode != MipmapMode::kNone) ? GrMipmapped::kYes
|
||||||
context->priv().caps()->mipmapSupport()
|
: GrMipmapped::kNo;
|
||||||
? GrMipmapped::kYes : GrMipmapped::kNo;
|
if (mipmapped == GrMipmapped::kYes && !context->priv().caps()->mipmapSupport()) {
|
||||||
|
return DrawResult::kSkip;
|
||||||
|
}
|
||||||
GrBitmapTextureMaker maker(context, fBitmap, GrImageTexGenPolicy::kDraw);
|
GrBitmapTextureMaker maker(context, fBitmap, GrImageTexGenPolicy::kDraw);
|
||||||
auto view = maker.view(mipMapped);
|
auto view = maker.view(mipmapped);
|
||||||
if (!view) {
|
if (!view) {
|
||||||
*errorMsg = "Failed to create proxy.";
|
*errorMsg = "Failed to create proxy.";
|
||||||
return DrawResult::kFail;
|
return DrawResult::kFail;
|
||||||
@ -115,7 +126,7 @@ protected:
|
|||||||
fBitmap.extractSubset(&subsetBmp, texelSubset);
|
fBitmap.extractSubset(&subsetBmp, texelSubset);
|
||||||
subsetBmp.setImmutable();
|
subsetBmp.setImmutable();
|
||||||
GrBitmapTextureMaker subsetMaker(context, subsetBmp, GrImageTexGenPolicy::kDraw);
|
GrBitmapTextureMaker subsetMaker(context, subsetBmp, GrImageTexGenPolicy::kDraw);
|
||||||
auto subsetView = subsetMaker.view(mipMapped);
|
auto subsetView = subsetMaker.view(mipmapped);
|
||||||
|
|
||||||
SkRect localRect = SkRect::Make(fBitmap.bounds()).makeOutset(kDrawPad, kDrawPad);
|
SkRect localRect = SkRect::Make(fBitmap.bounds()).makeOutset(kDrawPad, kDrawPad);
|
||||||
|
|
||||||
@ -126,13 +137,13 @@ protected:
|
|||||||
for (int tm = 0; tm < textureMatrices.count(); ++tm) {
|
for (int tm = 0; tm < textureMatrices.count(); ++tm) {
|
||||||
for (int my = 0; my < GrSamplerState::kWrapModeCount; ++my) {
|
for (int my = 0; my < GrSamplerState::kWrapModeCount; ++my) {
|
||||||
SkScalar x = kDrawPad + kTestPad;
|
SkScalar x = kDrawPad + kTestPad;
|
||||||
auto wmy = static_cast<GrSamplerState::WrapMode>(my);
|
auto wmy = static_cast<Wrap>(my);
|
||||||
for (int mx = 0; mx < GrSamplerState::kWrapModeCount; ++mx) {
|
for (int mx = 0; mx < GrSamplerState::kWrapModeCount; ++mx) {
|
||||||
auto wmx = static_cast<GrSamplerState::WrapMode>(mx);
|
auto wmx = static_cast<Wrap>(mx);
|
||||||
|
|
||||||
const auto& caps = *context->priv().caps();
|
const auto& caps = *context->priv().caps();
|
||||||
|
|
||||||
GrSamplerState sampler(wmx, wmy, fFilter);
|
GrSamplerState sampler(wmx, wmy, fFilter, fMipmapMode);
|
||||||
|
|
||||||
drawRect = localRect.makeOffset(x, y);
|
drawRect = localRect.makeOffset(x, y);
|
||||||
|
|
||||||
@ -166,9 +177,11 @@ protected:
|
|||||||
SkMatrix subsetTextureMatrix = SkMatrix::Concat(
|
SkMatrix subsetTextureMatrix = SkMatrix::Concat(
|
||||||
SkMatrix::Translate(-texelSubset.topLeft()), textureMatrices[tm]);
|
SkMatrix::Translate(-texelSubset.topLeft()), textureMatrices[tm]);
|
||||||
|
|
||||||
auto fp2 = GrTextureEffect::Make(subsetView, fBitmap.alphaType(),
|
auto fp2 = GrTextureEffect::Make(subsetView,
|
||||||
|
fBitmap.alphaType(),
|
||||||
subsetTextureMatrix,
|
subsetTextureMatrix,
|
||||||
GrSamplerState(wmx, wmy, fFilter), caps);
|
sampler,
|
||||||
|
caps);
|
||||||
if (auto op = sk_gpu_test::test_ops::MakeRect(context, std::move(fp2), drawRect,
|
if (auto op = sk_gpu_test::test_ops::MakeRect(context, std::move(fp2), drawRect,
|
||||||
localRect)) {
|
localRect)) {
|
||||||
renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
|
renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
|
||||||
@ -202,17 +215,19 @@ private:
|
|||||||
static constexpr SkScalar kDrawPad = 10.f;
|
static constexpr SkScalar kDrawPad = 10.f;
|
||||||
static constexpr SkScalar kTestPad = 10.f;
|
static constexpr SkScalar kTestPad = 10.f;
|
||||||
SkBitmap fBitmap;
|
SkBitmap fBitmap;
|
||||||
GrSamplerState::Filter fFilter;
|
Filter fFilter;
|
||||||
|
MipmapMode fMipmapMode;
|
||||||
bool fUpscale;
|
bool fUpscale;
|
||||||
|
|
||||||
typedef GM INHERITED;
|
typedef GM INHERITED;
|
||||||
};
|
};
|
||||||
|
|
||||||
DEF_GM(return new TexelSubset(GrSamplerState::Filter::kNearest, false);)
|
DEF_GM(return new TexelSubset(Filter::kNearest, MipmapMode::kNone , false);)
|
||||||
DEF_GM(return new TexelSubset(GrSamplerState::Filter::kNearest, true);)
|
DEF_GM(return new TexelSubset(Filter::kNearest, MipmapMode::kNone , true);)
|
||||||
DEF_GM(return new TexelSubset(GrSamplerState::Filter::kLinear , false);)
|
DEF_GM(return new TexelSubset(Filter::kLinear , MipmapMode::kNone , false);)
|
||||||
DEF_GM(return new TexelSubset(GrSamplerState::Filter::kLinear , true);)
|
DEF_GM(return new TexelSubset(Filter::kLinear , MipmapMode::kNone , true);)
|
||||||
// It doesn't make sense to have upscaling MIP map.
|
// It doesn't make sense to have upscaling MIP map.
|
||||||
DEF_GM(return new TexelSubset(GrSamplerState::Filter::kMipMap, false);)
|
DEF_GM(return new TexelSubset(Filter::kNearest, MipmapMode::kLinear, false);)
|
||||||
|
DEF_GM(return new TexelSubset(Filter::kLinear , MipmapMode::kLinear, false);)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -45,8 +45,7 @@ bool GrFragmentProcessor::isEqual(const GrFragmentProcessor& that) const {
|
|||||||
|
|
||||||
void GrFragmentProcessor::visitProxies(const GrOp::VisitProxyFunc& func) const {
|
void GrFragmentProcessor::visitProxies(const GrOp::VisitProxyFunc& func) const {
|
||||||
this->visitTextureEffects([&func](const GrTextureEffect& te) {
|
this->visitTextureEffects([&func](const GrTextureEffect& te) {
|
||||||
bool mipped = (GrSamplerState::Filter::kMipMap == te.samplerState().filter());
|
func(te.view().proxy(), te.samplerState().mipmapped());
|
||||||
func(te.view().proxy(), GrMipmapped(mipped));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,11 +70,10 @@ std::unique_ptr<GrFragmentProcessor> GrYUVAImageTextureMaker::createFragmentProc
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check to see if the client has given us pre-mipped textures or we can generate them
|
// Check to see if the client has given us pre-mipped textures or we can generate them
|
||||||
// If not, fall back to linear filtering. Also fall back to linear filtering when a domain is
|
// If not disable mip mapping. Also disable when a subset is requested.
|
||||||
// requested.
|
if (samplerState.mipmapped() == GrMipmapped::kYes &&
|
||||||
if (samplerState.filter() == GrSamplerState::Filter::kMipMap &&
|
|
||||||
(subset || !fImage->setupMipmapsForPlanes(this->context()))) {
|
(subset || !fImage->setupMipmapsForPlanes(this->context()))) {
|
||||||
samplerState.setFilterMode(GrSamplerState::Filter::kLinear);
|
samplerState.setMipmapMode(GrSamplerState::MipmapMode::kNone);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& caps = *fImage->context()->priv().caps();
|
const auto& caps = *fImage->context()->priv().caps();
|
||||||
|
@ -158,7 +158,7 @@ void GrOpsRenderPass::bindTextures(const GrPrimitiveProcessor& primProc,
|
|||||||
|
|
||||||
const GrTexture* tex = proxy->peekTexture();
|
const GrTexture* tex = proxy->peekTexture();
|
||||||
SkASSERT(tex);
|
SkASSERT(tex);
|
||||||
if (GrSamplerState::Filter::kMipMap == sampler.samplerState().filter() &&
|
if (sampler.samplerState().mipmapped() == GrMipmapped::kYes &&
|
||||||
(tex->width() != 1 || tex->height() != 1)) {
|
(tex->width() != 1 || tex->height() != 1)) {
|
||||||
// There are some cases where we might be given a non-mipmapped texture with a mipmap
|
// There are some cases where we might be given a non-mipmapped texture with a mipmap
|
||||||
// filter. See skbug.com/7094.
|
// filter. See skbug.com/7094.
|
||||||
|
@ -43,7 +43,7 @@ void GrProgramInfo::checkMSAAAndMIPSAreResolved() const {
|
|||||||
SkASSERT(tex);
|
SkASSERT(tex);
|
||||||
|
|
||||||
// Ensure mipmaps were all resolved ahead of time by the DAG.
|
// Ensure mipmaps were all resolved ahead of time by the DAG.
|
||||||
if (GrSamplerState::Filter::kMipMap == te.samplerState().filter() &&
|
if (te.samplerState().mipmapped() == GrMipmapped::kYes &&
|
||||||
(tex->width() != 1 || tex->height() != 1)) {
|
(tex->width() != 1 || tex->height() != 1)) {
|
||||||
// There are some cases where we might be given a non-mipmapped texture with a
|
// There are some cases where we might be given a non-mipmapped texture with a
|
||||||
// mipmap filter. See skbug.com/7094.
|
// mipmap filter. See skbug.com/7094.
|
||||||
|
@ -798,6 +798,7 @@ void GrRenderTargetContext::drawTexturedQuad(const GrClip* clip,
|
|||||||
SkAlphaType srcAlphaType,
|
SkAlphaType srcAlphaType,
|
||||||
sk_sp<GrColorSpaceXform> textureXform,
|
sk_sp<GrColorSpaceXform> textureXform,
|
||||||
GrSamplerState::Filter filter,
|
GrSamplerState::Filter filter,
|
||||||
|
GrSamplerState::MipmapMode mm,
|
||||||
const SkPMColor4f& color,
|
const SkPMColor4f& color,
|
||||||
SkBlendMode blendMode,
|
SkBlendMode blendMode,
|
||||||
GrAA aa,
|
GrAA aa,
|
||||||
@ -827,7 +828,7 @@ void GrRenderTargetContext::drawTexturedQuad(const GrClip* clip,
|
|||||||
// quad is sufficiently inside the subset and the constraint could be dropped.
|
// quad is sufficiently inside the subset and the constraint could be dropped.
|
||||||
this->addDrawOp(finalClip,
|
this->addDrawOp(finalClip,
|
||||||
GrTextureOp::Make(fContext, std::move(proxyView), srcAlphaType,
|
GrTextureOp::Make(fContext, std::move(proxyView), srcAlphaType,
|
||||||
std::move(textureXform), filter, color, saturate,
|
std::move(textureXform), filter, mm, color, saturate,
|
||||||
blendMode, aaType, quad, subset));
|
blendMode, aaType, quad, subset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1007,10 +1008,15 @@ void GrRenderTargetContextPriv::stencilPath(const GrHardClip* clip,
|
|||||||
fRenderTargetContext->addOp(std::move(op));
|
fRenderTargetContext->addOp(std::move(op));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrRenderTargetContext::drawTextureSet(const GrClip* clip, TextureSetEntry set[],
|
void GrRenderTargetContext::drawTextureSet(const GrClip* clip,
|
||||||
int cnt, int proxyRunCnt,
|
TextureSetEntry set[],
|
||||||
GrSamplerState::Filter filter, SkBlendMode mode,
|
int cnt,
|
||||||
GrAA aa, SkCanvas::SrcRectConstraint constraint,
|
int proxyRunCnt,
|
||||||
|
GrSamplerState::Filter filter,
|
||||||
|
GrSamplerState::MipmapMode mm,
|
||||||
|
SkBlendMode mode,
|
||||||
|
GrAA aa,
|
||||||
|
SkCanvas::SrcRectConstraint constraint,
|
||||||
const SkMatrix& viewMatrix,
|
const SkMatrix& viewMatrix,
|
||||||
sk_sp<GrColorSpaceXform> texXform) {
|
sk_sp<GrColorSpaceXform> texXform) {
|
||||||
ASSERT_SINGLE_OWNER
|
ASSERT_SINGLE_OWNER
|
||||||
@ -1025,7 +1031,7 @@ void GrRenderTargetContext::drawTextureSet(const GrClip* clip, TextureSetEntry s
|
|||||||
auto clampType = GrColorTypeClampType(this->colorInfo().colorType());
|
auto clampType = GrColorTypeClampType(this->colorInfo().colorType());
|
||||||
auto saturate = clampType == GrClampType::kManual ? GrTextureOp::Saturate::kYes
|
auto saturate = clampType == GrClampType::kManual ? GrTextureOp::Saturate::kYes
|
||||||
: GrTextureOp::Saturate::kNo;
|
: GrTextureOp::Saturate::kNo;
|
||||||
GrTextureOp::AddTextureSetOps(this, clip, fContext, set, cnt, proxyRunCnt, filter, saturate,
|
GrTextureOp::AddTextureSetOps(this, clip, fContext, set, cnt, proxyRunCnt, filter, mm, saturate,
|
||||||
mode, aaType, constraint, viewMatrix, std::move(texXform));
|
mode, aaType, constraint, viewMatrix, std::move(texXform));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,17 +270,26 @@ public:
|
|||||||
* specifies the rectangle to draw in local coords which will be transformed by 'viewMatrix' to
|
* specifies the rectangle to draw in local coords which will be transformed by 'viewMatrix' to
|
||||||
* device space.
|
* device space.
|
||||||
*/
|
*/
|
||||||
void drawTexture(const GrClip* clip, GrSurfaceProxyView view, SkAlphaType srcAlphaType,
|
void drawTexture(const GrClip* clip,
|
||||||
GrSamplerState::Filter filter, SkBlendMode mode, const SkPMColor4f& color,
|
GrSurfaceProxyView view,
|
||||||
const SkRect& srcRect, const SkRect& dstRect, GrAA aa, GrQuadAAFlags edgeAA,
|
SkAlphaType srcAlphaType,
|
||||||
SkCanvas::SrcRectConstraint constraint, const SkMatrix& viewMatrix,
|
GrSamplerState::Filter filter,
|
||||||
|
GrSamplerState::MipmapMode mm,
|
||||||
|
SkBlendMode mode,
|
||||||
|
const SkPMColor4f& color,
|
||||||
|
const SkRect& srcRect,
|
||||||
|
const SkRect& dstRect,
|
||||||
|
GrAA aa,
|
||||||
|
GrQuadAAFlags edgeAA,
|
||||||
|
SkCanvas::SrcRectConstraint constraint,
|
||||||
|
const SkMatrix& viewMatrix,
|
||||||
sk_sp<GrColorSpaceXform> texXform) {
|
sk_sp<GrColorSpaceXform> texXform) {
|
||||||
const SkRect* subset = constraint == SkCanvas::kStrict_SrcRectConstraint ?
|
const SkRect* subset = constraint == SkCanvas::kStrict_SrcRectConstraint ?
|
||||||
&srcRect : nullptr;
|
&srcRect : nullptr;
|
||||||
DrawQuad quad{GrQuad::MakeFromRect(dstRect, viewMatrix), GrQuad(srcRect), edgeAA};
|
DrawQuad quad{GrQuad::MakeFromRect(dstRect, viewMatrix), GrQuad(srcRect), edgeAA};
|
||||||
|
|
||||||
this->drawTexturedQuad(clip, std::move(view), srcAlphaType, std::move(texXform),
|
this->drawTexturedQuad(clip, std::move(view), srcAlphaType, std::move(texXform), filter, mm,
|
||||||
filter, color, mode, aa, &quad, subset);
|
color, mode, aa, &quad, subset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -289,16 +298,25 @@ public:
|
|||||||
* 'subset' is null, it's equivalent to using the fast src rect constraint. If 'subset' is
|
* 'subset' is null, it's equivalent to using the fast src rect constraint. If 'subset' is
|
||||||
* provided, the strict src rect constraint is applied using 'subset'.
|
* provided, the strict src rect constraint is applied using 'subset'.
|
||||||
*/
|
*/
|
||||||
void drawTextureQuad(const GrClip* clip, GrSurfaceProxyView view, GrColorType srcColorType,
|
void drawTextureQuad(const GrClip* clip,
|
||||||
SkAlphaType srcAlphaType, GrSamplerState::Filter filter, SkBlendMode mode,
|
GrSurfaceProxyView view,
|
||||||
const SkPMColor4f& color, const SkPoint srcQuad[4],
|
GrColorType srcColorType,
|
||||||
const SkPoint dstQuad[4], GrAA aa, GrQuadAAFlags edgeAA,
|
SkAlphaType srcAlphaType,
|
||||||
const SkRect* subset, const SkMatrix& viewMatrix,
|
GrSamplerState::Filter filter,
|
||||||
|
GrSamplerState::MipmapMode mm,
|
||||||
|
SkBlendMode mode,
|
||||||
|
const SkPMColor4f& color,
|
||||||
|
const SkPoint srcQuad[4],
|
||||||
|
const SkPoint dstQuad[4],
|
||||||
|
GrAA aa,
|
||||||
|
GrQuadAAFlags edgeAA,
|
||||||
|
const SkRect* subset,
|
||||||
|
const SkMatrix& viewMatrix,
|
||||||
sk_sp<GrColorSpaceXform> texXform) {
|
sk_sp<GrColorSpaceXform> texXform) {
|
||||||
DrawQuad quad{GrQuad::MakeFromSkQuad(dstQuad, viewMatrix),
|
DrawQuad quad{GrQuad::MakeFromSkQuad(dstQuad, viewMatrix),
|
||||||
GrQuad::MakeFromSkQuad(srcQuad, SkMatrix::I()), edgeAA};
|
GrQuad::MakeFromSkQuad(srcQuad, SkMatrix::I()), edgeAA};
|
||||||
this->drawTexturedQuad(clip, std::move(view), srcAlphaType, std::move(texXform),
|
this->drawTexturedQuad(clip, std::move(view), srcAlphaType, std::move(texXform), filter, mm,
|
||||||
filter, color, mode, aa, &quad, subset);
|
color, mode, aa, &quad, subset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Used with drawTextureSet */
|
/** Used with drawTextureSet */
|
||||||
@ -323,9 +341,16 @@ public:
|
|||||||
* can be inferred from the array within this function, but the information is already known
|
* can be inferred from the array within this function, but the information is already known
|
||||||
* by SkGpuDevice, so no need to incur another iteration over the array.
|
* by SkGpuDevice, so no need to incur another iteration over the array.
|
||||||
*/
|
*/
|
||||||
void drawTextureSet(const GrClip*, TextureSetEntry[], int cnt, int proxyRunCnt,
|
void drawTextureSet(const GrClip*,
|
||||||
GrSamplerState::Filter, SkBlendMode mode, GrAA aa,
|
TextureSetEntry[],
|
||||||
SkCanvas::SrcRectConstraint, const SkMatrix& viewMatrix,
|
int cnt,
|
||||||
|
int proxyRunCnt,
|
||||||
|
GrSamplerState::Filter,
|
||||||
|
GrSamplerState::MipmapMode,
|
||||||
|
SkBlendMode mode,
|
||||||
|
GrAA aa,
|
||||||
|
SkCanvas::SrcRectConstraint,
|
||||||
|
const SkMatrix& viewMatrix,
|
||||||
sk_sp<GrColorSpaceXform> texXform);
|
sk_sp<GrColorSpaceXform> texXform);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -645,6 +670,7 @@ private:
|
|||||||
SkAlphaType alphaType,
|
SkAlphaType alphaType,
|
||||||
sk_sp<GrColorSpaceXform> textureXform,
|
sk_sp<GrColorSpaceXform> textureXform,
|
||||||
GrSamplerState::Filter filter,
|
GrSamplerState::Filter filter,
|
||||||
|
GrSamplerState::MipmapMode,
|
||||||
const SkPMColor4f& color,
|
const SkPMColor4f& color,
|
||||||
SkBlendMode blendMode,
|
SkBlendMode blendMode,
|
||||||
GrAA aa,
|
GrAA aa,
|
||||||
|
@ -16,48 +16,71 @@
|
|||||||
*/
|
*/
|
||||||
class GrSamplerState {
|
class GrSamplerState {
|
||||||
public:
|
public:
|
||||||
enum class Filter : uint8_t { kNearest, kLinear, kMipMap, kLast = kMipMap };
|
enum class Filter : uint8_t { kNearest, kLinear, kLast = kLinear };
|
||||||
enum class WrapMode : uint8_t { kClamp, kRepeat, kMirrorRepeat, kClampToBorder,
|
enum class MipmapMode : uint8_t { kNone, /*kNearest,*/ kLinear, kLast = kLinear };
|
||||||
kLast = kClampToBorder };
|
|
||||||
|
enum class WrapMode : uint8_t {
|
||||||
|
kClamp,
|
||||||
|
kRepeat,
|
||||||
|
kMirrorRepeat,
|
||||||
|
kClampToBorder,
|
||||||
|
kLast = kClampToBorder
|
||||||
|
};
|
||||||
|
|
||||||
static constexpr int kFilterCount = static_cast<int>(Filter::kLast) + 1;
|
static constexpr int kFilterCount = static_cast<int>(Filter::kLast) + 1;
|
||||||
static constexpr int kWrapModeCount = static_cast<int>(WrapMode::kLast) + 1;
|
static constexpr int kWrapModeCount = static_cast<int>(WrapMode::kLast) + 1;
|
||||||
|
|
||||||
constexpr GrSamplerState() = default;
|
constexpr GrSamplerState() = default;
|
||||||
|
|
||||||
constexpr GrSamplerState(WrapMode wrapXAndY, Filter filter)
|
constexpr GrSamplerState(WrapMode wrapXAndY, Filter filter, MipmapMode mm = MipmapMode::kNone)
|
||||||
: fWrapModes{wrapXAndY, wrapXAndY}, fFilter(filter) {}
|
: fWrapModes{wrapXAndY, wrapXAndY}, fFilter(filter), fMipmapMode(mm) {}
|
||||||
|
|
||||||
constexpr GrSamplerState(WrapMode wrapX, WrapMode wrapY, Filter filter)
|
constexpr GrSamplerState(WrapMode wrapX,
|
||||||
: fWrapModes{wrapX, wrapY}, fFilter(filter) {}
|
WrapMode wrapY,
|
||||||
|
Filter filter,
|
||||||
|
MipmapMode mm = MipmapMode::kNone)
|
||||||
|
: fWrapModes{wrapX, wrapY}, fFilter(filter), fMipmapMode(mm) {}
|
||||||
|
|
||||||
constexpr GrSamplerState(const WrapMode wrapModes[2], Filter filter)
|
constexpr GrSamplerState(const WrapMode wrapModes[2],
|
||||||
: fWrapModes{wrapModes[0], wrapModes[1]}, fFilter(filter) {}
|
Filter filter,
|
||||||
|
MipmapMode mm = MipmapMode::kNone)
|
||||||
|
: fWrapModes{wrapModes[0], wrapModes[1]}, fFilter(filter), fMipmapMode(mm) {}
|
||||||
|
|
||||||
constexpr /*explicit*/ GrSamplerState(Filter filter) : fFilter(filter) {}
|
constexpr /*explicit*/ GrSamplerState(Filter filter) : fFilter(filter) {}
|
||||||
|
constexpr GrSamplerState(Filter filter, MipmapMode mm) : fFilter(filter), fMipmapMode(mm) {}
|
||||||
|
|
||||||
constexpr GrSamplerState(const GrSamplerState&) = default;
|
constexpr GrSamplerState(const GrSamplerState&) = default;
|
||||||
|
|
||||||
constexpr GrSamplerState& operator=(const GrSamplerState&) = default;
|
constexpr GrSamplerState& operator=(const GrSamplerState&) = default;
|
||||||
|
|
||||||
constexpr Filter filter() const { return fFilter; }
|
|
||||||
|
|
||||||
constexpr void setFilterMode(Filter filterMode) { fFilter = filterMode; }
|
|
||||||
|
|
||||||
constexpr void setWrapModeX(const WrapMode wrap) { fWrapModes[0] = wrap; }
|
|
||||||
constexpr void setWrapModeY(const WrapMode wrap) { fWrapModes[1] = wrap; }
|
|
||||||
|
|
||||||
constexpr WrapMode wrapModeX() const { return fWrapModes[0]; }
|
constexpr WrapMode wrapModeX() const { return fWrapModes[0]; }
|
||||||
|
|
||||||
constexpr WrapMode wrapModeY() const { return fWrapModes[1]; }
|
constexpr WrapMode wrapModeY() const { return fWrapModes[1]; }
|
||||||
|
|
||||||
constexpr bool isRepeated() const {
|
constexpr bool isRepeated() const {
|
||||||
return (WrapMode::kClamp != fWrapModes[0] && WrapMode::kClampToBorder != fWrapModes[0]) ||
|
return fWrapModes[0] == WrapMode::kRepeat || fWrapModes[0] == WrapMode::kMirrorRepeat ||
|
||||||
(WrapMode::kClamp != fWrapModes[1] && WrapMode::kClampToBorder != fWrapModes[1]);
|
fWrapModes[1] == WrapMode::kRepeat || fWrapModes[1] == WrapMode::kMirrorRepeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr Filter filter() const { return fFilter; }
|
||||||
|
|
||||||
|
constexpr MipmapMode mipmapMode() const { return fMipmapMode; }
|
||||||
|
|
||||||
|
constexpr GrMipmapped mipmapped() const {
|
||||||
|
return GrMipmapped(fMipmapMode != MipmapMode::kNone);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void setFilterMode(Filter filterMode) { fFilter = filterMode; }
|
||||||
|
|
||||||
|
constexpr void setMipmapMode(MipmapMode mm) { fMipmapMode = mm; }
|
||||||
|
|
||||||
|
constexpr void setWrapModeX(const WrapMode wrap) { fWrapModes[0] = wrap; }
|
||||||
|
|
||||||
|
constexpr void setWrapModeY(const WrapMode wrap) { fWrapModes[1] = wrap; }
|
||||||
|
|
||||||
constexpr bool operator==(GrSamplerState that) const {
|
constexpr bool operator==(GrSamplerState that) const {
|
||||||
return fWrapModes[0] == that.fWrapModes[0] && fWrapModes[1] == that.fWrapModes[1] &&
|
return fWrapModes[0] == that.fWrapModes[0] && fWrapModes[1] == that.fWrapModes[1] &&
|
||||||
fFilter == that.fFilter;
|
fFilter == that.fFilter && fMipmapMode == that.fMipmapMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool operator!=(const GrSamplerState& that) const { return !(*this == that); }
|
constexpr bool operator!=(const GrSamplerState& that) const { return !(*this == that); }
|
||||||
@ -68,19 +91,23 @@ public:
|
|||||||
*/
|
*/
|
||||||
constexpr uint8_t asIndex() const {
|
constexpr uint8_t asIndex() const {
|
||||||
constexpr int kNumWraps = static_cast<int>(WrapMode::kLast) + 1;
|
constexpr int kNumWraps = static_cast<int>(WrapMode::kLast) + 1;
|
||||||
|
constexpr int kNumFilters = static_cast<int>(Filter::kLast ) + 1;
|
||||||
int result = static_cast<int>(fWrapModes[0])*1
|
int result = static_cast<int>(fWrapModes[0])*1
|
||||||
+ static_cast<int>(fWrapModes[1])*kNumWraps
|
+ static_cast<int>(fWrapModes[1])*kNumWraps
|
||||||
+ static_cast<int>(fFilter) *kNumWraps*kNumWraps;
|
+ static_cast<int>(fFilter) *kNumWraps*kNumWraps
|
||||||
|
+ static_cast<int>(fMipmapMode) *kNumWraps*kNumWraps*kNumFilters;
|
||||||
SkASSERT(result <= kNumUniqueSamplers);
|
SkASSERT(result <= kNumUniqueSamplers);
|
||||||
return static_cast<uint8_t>(result);
|
return static_cast<uint8_t>(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr int kNumUniqueSamplers = (static_cast<int>(WrapMode::kLast) + 1)
|
static constexpr int kNumUniqueSamplers = (static_cast<int>(WrapMode::kLast ) + 1)
|
||||||
* (static_cast<int>(WrapMode::kLast) + 1)
|
* (static_cast<int>(WrapMode::kLast ) + 1)
|
||||||
* (static_cast<int>(Filter::kLast ) + 1);
|
* (static_cast<int>(Filter::kLast ) + 1)
|
||||||
|
* (static_cast<int>(MipmapMode::kLast) + 1);
|
||||||
private:
|
private:
|
||||||
WrapMode fWrapModes[2] = {WrapMode::kClamp, WrapMode::kClamp};
|
WrapMode fWrapModes[2] = {WrapMode::kClamp, WrapMode::kClamp};
|
||||||
Filter fFilter = GrSamplerState::Filter::kNearest;
|
Filter fFilter = GrSamplerState::Filter::kNearest;
|
||||||
|
MipmapMode fMipmapMode = GrSamplerState::MipmapMode::kNone;
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(GrSamplerState::kNumUniqueSamplers <=
|
static_assert(GrSamplerState::kNumUniqueSamplers <=
|
||||||
|
@ -575,12 +575,20 @@ void GrSurfaceContext::asyncRescaleAndReadPixels(const SkImageInfo& info,
|
|||||||
callback(context, nullptr);
|
callback(context, nullptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tempRTC->drawTexture(nullptr, std::move(texProxyView), this->colorInfo().alphaType(),
|
tempRTC->drawTexture(nullptr,
|
||||||
GrSamplerState::Filter::kNearest, SkBlendMode::kSrc,
|
std::move(texProxyView),
|
||||||
SK_PMColor4fWHITE, srcRectToDraw,
|
this->colorInfo().alphaType(),
|
||||||
SkRect::MakeWH(srcRect.width(), srcRect.height()), GrAA::kNo,
|
GrSamplerState::Filter::kNearest,
|
||||||
GrQuadAAFlags::kNone, SkCanvas::kFast_SrcRectConstraint,
|
GrSamplerState::MipmapMode::kNone,
|
||||||
SkMatrix::I(), std::move(xform));
|
SkBlendMode::kSrc,
|
||||||
|
SK_PMColor4fWHITE,
|
||||||
|
srcRectToDraw,
|
||||||
|
SkRect::MakeWH(srcRect.width(), srcRect.height()),
|
||||||
|
GrAA::kNo,
|
||||||
|
GrQuadAAFlags::kNone,
|
||||||
|
SkCanvas::kFast_SrcRectConstraint,
|
||||||
|
SkMatrix::I(),
|
||||||
|
std::move(xform));
|
||||||
x = y = 0;
|
x = y = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -799,11 +807,20 @@ void GrSurfaceContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorS
|
|||||||
callback(context, nullptr);
|
callback(context, nullptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tempRTC->drawTexture(nullptr, std::move(srcView), this->colorInfo().alphaType(),
|
tempRTC->drawTexture(nullptr,
|
||||||
GrSamplerState::Filter::kNearest, SkBlendMode::kSrc,
|
std::move(srcView),
|
||||||
SK_PMColor4fWHITE, srcRectToDraw, SkRect::Make(srcRect.size()),
|
this->colorInfo().alphaType(),
|
||||||
GrAA::kNo, GrQuadAAFlags::kNone, SkCanvas::kFast_SrcRectConstraint,
|
GrSamplerState::Filter::kNearest,
|
||||||
SkMatrix::I(), std::move(xform));
|
GrSamplerState::MipmapMode::kNone,
|
||||||
|
SkBlendMode::kSrc,
|
||||||
|
SK_PMColor4fWHITE,
|
||||||
|
srcRectToDraw,
|
||||||
|
SkRect::Make(srcRect.size()),
|
||||||
|
GrAA::kNo,
|
||||||
|
GrQuadAAFlags::kNone,
|
||||||
|
SkCanvas::kFast_SrcRectConstraint,
|
||||||
|
SkMatrix::I(),
|
||||||
|
std::move(xform));
|
||||||
srcView = tempRTC->readSurfaceView();
|
srcView = tempRTC->readSurfaceView();
|
||||||
SkASSERT(srcView.asTextureProxy());
|
SkASSERT(srcView.asTextureProxy());
|
||||||
x = y = 0;
|
x = y = 0;
|
||||||
@ -1058,11 +1075,20 @@ std::unique_ptr<GrRenderTargetContext> GrSurfaceContext::rescale(const GrImageIn
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
// 1-to-1 draw can always be kFast.
|
// 1-to-1 draw can always be kFast.
|
||||||
linearRTC->drawTexture(nullptr, std::move(texView), srcAlphaType,
|
linearRTC->drawTexture(nullptr,
|
||||||
GrSamplerState::Filter::kNearest, SkBlendMode::kSrc,
|
std::move(texView),
|
||||||
SK_PMColor4fWHITE, SkRect::Make(srcRect),
|
srcAlphaType,
|
||||||
SkRect::Make(srcRect.size()), GrAA::kNo, GrQuadAAFlags::kNone,
|
GrSamplerState::Filter::kNearest,
|
||||||
SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(), std::move(xform));
|
GrSamplerState::MipmapMode::kNone,
|
||||||
|
SkBlendMode::kSrc,
|
||||||
|
SK_PMColor4fWHITE,
|
||||||
|
SkRect::Make(srcRect),
|
||||||
|
SkRect::Make(srcRect.size()),
|
||||||
|
GrAA::kNo,
|
||||||
|
GrQuadAAFlags::kNone,
|
||||||
|
SkCanvas::kFast_SrcRectConstraint,
|
||||||
|
SkMatrix::I(),
|
||||||
|
std::move(xform));
|
||||||
texView = linearRTC->readSurfaceView();
|
texView = linearRTC->readSurfaceView();
|
||||||
SkASSERT(texView.asTextureProxy());
|
SkASSERT(texView.asTextureProxy());
|
||||||
tempA = std::move(linearRTC);
|
tempA = std::move(linearRTC);
|
||||||
@ -1135,9 +1161,20 @@ std::unique_ptr<GrRenderTargetContext> GrSurfaceContext::rescale(const GrImageIn
|
|||||||
if (nextDims.width() <= srcRect.width() && nextDims.height() <= srcRect.height()) {
|
if (nextDims.width() <= srcRect.width() && nextDims.height() <= srcRect.height()) {
|
||||||
constraint = SkCanvas::SrcRectConstraint::kFast_SrcRectConstraint;
|
constraint = SkCanvas::SrcRectConstraint::kFast_SrcRectConstraint;
|
||||||
}
|
}
|
||||||
tempB->drawTexture(nullptr, std::move(texView), srcAlphaType, filter, SkBlendMode::kSrc,
|
tempB->drawTexture(nullptr,
|
||||||
SK_PMColor4fWHITE, SkRect::Make(srcRect), dstRect, GrAA::kNo,
|
std::move(texView),
|
||||||
GrQuadAAFlags::kNone, constraint, SkMatrix::I(), std::move(xform));
|
srcAlphaType,
|
||||||
|
filter,
|
||||||
|
GrSamplerState::MipmapMode::kNone,
|
||||||
|
SkBlendMode::kSrc,
|
||||||
|
SK_PMColor4fWHITE,
|
||||||
|
SkRect::Make(srcRect),
|
||||||
|
dstRect,
|
||||||
|
GrAA::kNo,
|
||||||
|
GrQuadAAFlags::kNone,
|
||||||
|
constraint,
|
||||||
|
SkMatrix::I(),
|
||||||
|
std::move(xform));
|
||||||
}
|
}
|
||||||
texView = tempB->readSurfaceView();
|
texView = tempB->readSurfaceView();
|
||||||
tempA = std::move(tempB);
|
tempA = std::move(tempB);
|
||||||
|
@ -81,7 +81,7 @@ std::unique_ptr<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor(
|
|||||||
const SkRect* domain,
|
const SkRect* domain,
|
||||||
GrSamplerState samplerState) {
|
GrSamplerState samplerState) {
|
||||||
return this->createFragmentProcessorForView(
|
return this->createFragmentProcessorForView(
|
||||||
this->view(samplerState.filter()), textureMatrix, subset, domain, samplerState);
|
this->view(samplerState.mipmapped()), textureMatrix, subset, domain, samplerState);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<GrFragmentProcessor> GrTextureAdjuster::createBicubicFragmentProcessor(
|
std::unique_ptr<GrFragmentProcessor> GrTextureAdjuster::createBicubicFragmentProcessor(
|
||||||
|
@ -29,7 +29,7 @@ std::unique_ptr<GrFragmentProcessor> GrTextureMaker::createFragmentProcessor(
|
|||||||
GrSamplerState sampler) {
|
GrSamplerState sampler) {
|
||||||
GrSurfaceProxyView view;
|
GrSurfaceProxyView view;
|
||||||
return this->createFragmentProcessorForView(
|
return this->createFragmentProcessorForView(
|
||||||
this->view(sampler.filter()), textureMatrix, subset, domain, sampler);
|
this->view(sampler.mipmapped()), textureMatrix, subset, domain, sampler);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<GrFragmentProcessor> GrTextureMaker::createBicubicFragmentProcessor(
|
std::unique_ptr<GrFragmentProcessor> GrTextureMaker::createBicubicFragmentProcessor(
|
||||||
|
@ -101,9 +101,3 @@ GrSurfaceProxyView GrTextureProducer::view(GrMipmapped mipMapped) {
|
|||||||
!caps->isFormatCopyable(result.proxy()->backendFormat()));
|
!caps->isFormatCopyable(result.proxy()->backendFormat()));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
GrSurfaceProxyView GrTextureProducer::view(GrSamplerState::Filter filter) {
|
|
||||||
auto mipMapped = filter == GrSamplerState::Filter::kMipMap ? GrMipmapped::kYes
|
|
||||||
: GrMipmapped::kNo;
|
|
||||||
return this->view(mipMapped);
|
|
||||||
}
|
|
||||||
|
@ -88,9 +88,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
GrSurfaceProxyView view(GrMipmapped);
|
GrSurfaceProxyView view(GrMipmapped);
|
||||||
|
|
||||||
/** Helper version of above that determines MIP mapping requirement from Filter. */
|
|
||||||
GrSurfaceProxyView view(GrSamplerState::Filter);
|
|
||||||
|
|
||||||
int width() const { return fImageInfo.width(); }
|
int width() const { return fImageInfo.width(); }
|
||||||
int height() const { return fImageInfo.height(); }
|
int height() const { return fImageInfo.height(); }
|
||||||
SkISize dimensions() const { return fImageInfo.dimensions(); }
|
SkISize dimensions() const { return fImageInfo.dimensions(); }
|
||||||
|
@ -147,11 +147,6 @@ size_t GrTextureProxy::onUninstantiatedGpuMemorySize(const GrCaps& caps) const {
|
|||||||
this->proxyMipmapped(), !this->priv().isExact());
|
this->proxyMipmapped(), !this->priv().isExact());
|
||||||
}
|
}
|
||||||
|
|
||||||
GrSamplerState::Filter GrTextureProxy::HighestFilterMode(GrTextureType textureType) {
|
|
||||||
return GrTextureTypeHasRestrictedSampling(textureType) ? GrSamplerState::Filter::kLinear
|
|
||||||
: GrSamplerState::Filter::kMipMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GrTextureProxy::ProxiesAreCompatibleAsDynamicState(const GrSurfaceProxy* first,
|
bool GrTextureProxy::ProxiesAreCompatibleAsDynamicState(const GrSurfaceProxy* first,
|
||||||
const GrSurfaceProxy* second) {
|
const GrSurfaceProxy* second) {
|
||||||
// In order to be compatible, the proxies should also have the same texture type. This is
|
// In order to be compatible, the proxies should also have the same texture type. This is
|
||||||
|
@ -58,9 +58,6 @@ public:
|
|||||||
return GrTextureTypeHasRestrictedSampling(this->textureType());
|
return GrTextureTypeHasRestrictedSampling(this->textureType());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the highest allowed filter mode for a given texture type
|
|
||||||
static GrSamplerState::Filter HighestFilterMode(const GrTextureType textureType);
|
|
||||||
|
|
||||||
// Returns true if the passed in proxies can be used as dynamic state together when flushing
|
// Returns true if the passed in proxies can be used as dynamic state together when flushing
|
||||||
// draws to the gpu. This accepts GrSurfaceProxy since the information needed is defined on
|
// draws to the gpu. This accepts GrSurfaceProxy since the information needed is defined on
|
||||||
// that type, but this function exists in GrTextureProxy because it's only relevant when the
|
// that type, but this function exists in GrTextureProxy because it's only relevant when the
|
||||||
|
@ -817,7 +817,6 @@ static GrSamplerState::Filter compute_lattice_filter_mode(const SkPaint& paint)
|
|||||||
if (paint.getFilterQuality() == kNone_SkFilterQuality) {
|
if (paint.getFilterQuality() == kNone_SkFilterQuality) {
|
||||||
return GrSamplerState::Filter::kNearest;
|
return GrSamplerState::Filter::kNearest;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GrSamplerState::Filter::kLinear;
|
return GrSamplerState::Filter::kLinear;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -861,7 +860,7 @@ void SkGpuDevice::drawProducerLattice(GrTextureProducer* producer,
|
|||||||
|
|
||||||
auto dstColorSpace = fRenderTargetContext->colorInfo().colorSpace();
|
auto dstColorSpace = fRenderTargetContext->colorInfo().colorSpace();
|
||||||
const GrSamplerState::Filter filter = compute_lattice_filter_mode(*paint);
|
const GrSamplerState::Filter filter = compute_lattice_filter_mode(*paint);
|
||||||
auto view = producer->view(filter);
|
auto view = producer->view(GrMipmapped::kNo);
|
||||||
if (!view) {
|
if (!view) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -336,10 +336,17 @@ static SkPMColor4f texture_color(SkColor4f paintColor, float entryAlpha, GrColor
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Assumes srcRect and dstRect have already been optimized to fit the proxy
|
// Assumes srcRect and dstRect have already been optimized to fit the proxy
|
||||||
static void draw_texture(GrRenderTargetContext* rtc, const GrClip* clip, const SkMatrix& ctm,
|
static void draw_texture(GrRenderTargetContext* rtc,
|
||||||
const SkPaint& paint, const SkRect& srcRect, const SkRect& dstRect,
|
const GrClip* clip,
|
||||||
const SkPoint dstClip[4], GrAA aa, GrQuadAAFlags aaFlags,
|
const SkMatrix& ctm,
|
||||||
SkCanvas::SrcRectConstraint constraint, GrSurfaceProxyView view,
|
const SkPaint& paint,
|
||||||
|
const SkRect& srcRect,
|
||||||
|
const SkRect& dstRect,
|
||||||
|
const SkPoint dstClip[4],
|
||||||
|
GrAA aa,
|
||||||
|
GrQuadAAFlags aaFlags,
|
||||||
|
SkCanvas::SrcRectConstraint constraint,
|
||||||
|
GrSurfaceProxyView view,
|
||||||
const GrColorInfo& srcColorInfo) {
|
const GrColorInfo& srcColorInfo) {
|
||||||
const GrColorInfo& dstInfo(rtc->colorInfo());
|
const GrColorInfo& dstInfo(rtc->colorInfo());
|
||||||
auto textureXform =
|
auto textureXform =
|
||||||
@ -378,15 +385,36 @@ static void draw_texture(GrRenderTargetContext* rtc, const GrClip* clip, const S
|
|||||||
SkPoint srcQuad[4];
|
SkPoint srcQuad[4];
|
||||||
GrMapRectPoints(dstRect, srcRect, dstClip, srcQuad, 4);
|
GrMapRectPoints(dstRect, srcRect, dstClip, srcQuad, 4);
|
||||||
|
|
||||||
rtc->drawTextureQuad(clip, std::move(view), srcColorInfo.colorType(),
|
rtc->drawTextureQuad(clip,
|
||||||
srcColorInfo.alphaType(), filter, paint.getBlendMode(), color, srcQuad,
|
std::move(view),
|
||||||
dstClip, aa, aaFlags,
|
srcColorInfo.colorType(),
|
||||||
|
srcColorInfo.alphaType(),
|
||||||
|
filter,
|
||||||
|
GrSamplerState::MipmapMode::kNone,
|
||||||
|
paint.getBlendMode(),
|
||||||
|
color,
|
||||||
|
srcQuad,
|
||||||
|
dstClip,
|
||||||
|
aa,
|
||||||
|
aaFlags,
|
||||||
constraint == SkCanvas::kStrict_SrcRectConstraint ? &srcRect : nullptr,
|
constraint == SkCanvas::kStrict_SrcRectConstraint ? &srcRect : nullptr,
|
||||||
ctm, std::move(textureXform));
|
ctm,
|
||||||
|
std::move(textureXform));
|
||||||
} else {
|
} else {
|
||||||
rtc->drawTexture(clip, std::move(view), srcColorInfo.alphaType(), filter,
|
rtc->drawTexture(clip,
|
||||||
paint.getBlendMode(), color, srcRect, dstRect, aa, aaFlags, constraint,
|
std::move(view),
|
||||||
ctm, std::move(textureXform));
|
srcColorInfo.alphaType(),
|
||||||
|
filter,
|
||||||
|
GrSamplerState::MipmapMode::kNone,
|
||||||
|
paint.getBlendMode(),
|
||||||
|
color,
|
||||||
|
srcRect,
|
||||||
|
dstRect,
|
||||||
|
aa,
|
||||||
|
aaFlags,
|
||||||
|
constraint,
|
||||||
|
ctm,
|
||||||
|
std::move(textureXform));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,11 +432,11 @@ static void draw_texture_producer(GrRecordingContext* context,
|
|||||||
GrAA aa,
|
GrAA aa,
|
||||||
GrQuadAAFlags aaFlags,
|
GrQuadAAFlags aaFlags,
|
||||||
SkCanvas::SrcRectConstraint constraint,
|
SkCanvas::SrcRectConstraint constraint,
|
||||||
GrSamplerState::WrapMode wm,
|
GrSamplerState sampler,
|
||||||
GrSamplerState::Filter fm,
|
|
||||||
bool doBicubic) {
|
bool doBicubic) {
|
||||||
const SkMatrix& ctm(matrixProvider.localToDevice());
|
const SkMatrix& ctm(matrixProvider.localToDevice());
|
||||||
if (wm == GrSamplerState::WrapMode::kClamp && !producer->isPlanar() &&
|
if (sampler.wrapModeX() == GrSamplerState::WrapMode::kClamp &&
|
||||||
|
sampler.wrapModeY() == GrSamplerState::WrapMode::kClamp && !producer->isPlanar() &&
|
||||||
can_use_draw_texture(paint)) {
|
can_use_draw_texture(paint)) {
|
||||||
// We've done enough checks above to allow us to pass ClampNearest() and not check for
|
// We've done enough checks above to allow us to pass ClampNearest() and not check for
|
||||||
// scaling adjustments.
|
// scaling adjustments.
|
||||||
@ -446,8 +474,9 @@ static void draw_texture_producer(GrRecordingContext* context,
|
|||||||
bool coordsAllInsideSrcRect = aaFlags == GrQuadAAFlags::kNone && !mf;
|
bool coordsAllInsideSrcRect = aaFlags == GrQuadAAFlags::kNone && !mf;
|
||||||
|
|
||||||
// Check for optimization to drop the src rect constraint when using linear filtering.
|
// Check for optimization to drop the src rect constraint when using linear filtering.
|
||||||
if (!doBicubic && fm == GrSamplerState::Filter::kLinear && restrictToSubset &&
|
if (!doBicubic && sampler.filter() == GrSamplerState::Filter::kLinear && restrictToSubset &&
|
||||||
coordsAllInsideSrcRect && !producer->isPlanar()) {
|
sampler.mipmapped() == GrMipmapped::kNo && coordsAllInsideSrcRect &&
|
||||||
|
!producer->isPlanar()) {
|
||||||
SkMatrix combinedMatrix;
|
SkMatrix combinedMatrix;
|
||||||
combinedMatrix.setConcat(ctm, srcToDst);
|
combinedMatrix.setConcat(ctm, srcToDst);
|
||||||
if (can_ignore_linear_filtering_subset(*producer, src, combinedMatrix, rtc->numSamples())) {
|
if (can_ignore_linear_filtering_subset(*producer, src, combinedMatrix, rtc->numSamples())) {
|
||||||
@ -467,9 +496,10 @@ static void draw_texture_producer(GrRecordingContext* context,
|
|||||||
const SkRect* domain = coordsAllInsideSrcRect ? &src : nullptr;
|
const SkRect* domain = coordsAllInsideSrcRect ? &src : nullptr;
|
||||||
std::unique_ptr<GrFragmentProcessor> fp;
|
std::unique_ptr<GrFragmentProcessor> fp;
|
||||||
if (doBicubic) {
|
if (doBicubic) {
|
||||||
fp = producer->createBicubicFragmentProcessor(textureMatrix, subset, domain, wm, wm);
|
fp = producer->createBicubicFragmentProcessor(textureMatrix, subset, domain,
|
||||||
|
sampler.wrapModeX(), sampler.wrapModeY());
|
||||||
} else {
|
} else {
|
||||||
fp = producer->createFragmentProcessor(textureMatrix, subset, domain, {wm, fm});
|
fp = producer->createFragmentProcessor(textureMatrix, subset, domain, sampler);
|
||||||
}
|
}
|
||||||
if (fp) {
|
if (fp) {
|
||||||
fp = GrXfermodeFragmentProcessor::Make(std::move(fp), nullptr, SkBlendMode::kModulate);
|
fp = GrXfermodeFragmentProcessor::Make(std::move(fp), nullptr, SkBlendMode::kModulate);
|
||||||
@ -534,8 +564,7 @@ void draw_tiled_bitmap(GrRecordingContext* context,
|
|||||||
const SkPaint& paint,
|
const SkPaint& paint,
|
||||||
GrAA aa,
|
GrAA aa,
|
||||||
SkCanvas::SrcRectConstraint constraint,
|
SkCanvas::SrcRectConstraint constraint,
|
||||||
GrSamplerState::WrapMode wm,
|
GrSamplerState sampler,
|
||||||
GrSamplerState::Filter fm,
|
|
||||||
bool doBicubic) {
|
bool doBicubic) {
|
||||||
SkRect clippedSrcRect = SkRect::Make(clippedSrcIRect);
|
SkRect clippedSrcRect = SkRect::Make(clippedSrcIRect);
|
||||||
|
|
||||||
@ -562,7 +591,7 @@ void draw_tiled_bitmap(GrRecordingContext* context,
|
|||||||
SkIntToScalar(iTileR.fTop));
|
SkIntToScalar(iTileR.fTop));
|
||||||
SkRect rectToDraw = tileR;
|
SkRect rectToDraw = tileR;
|
||||||
srcToDst.mapRect(&rectToDraw);
|
srcToDst.mapRect(&rectToDraw);
|
||||||
if (fm != GrSamplerState::Filter::kNearest || doBicubic) {
|
if (sampler.filter() != GrSamplerState::Filter::kNearest || doBicubic) {
|
||||||
SkIRect iClampRect;
|
SkIRect iClampRect;
|
||||||
|
|
||||||
if (SkCanvas::kFast_SrcRectConstraint == constraint) {
|
if (SkCanvas::kFast_SrcRectConstraint == constraint) {
|
||||||
@ -611,10 +640,9 @@ void draw_tiled_bitmap(GrRecordingContext* context,
|
|||||||
tileR.offset(-offset.fX, -offset.fY);
|
tileR.offset(-offset.fX, -offset.fY);
|
||||||
SkMatrix offsetSrcToDst = srcToDst;
|
SkMatrix offsetSrcToDst = srcToDst;
|
||||||
offsetSrcToDst.preTranslate(offset.fX, offset.fY);
|
offsetSrcToDst.preTranslate(offset.fX, offset.fY);
|
||||||
|
|
||||||
draw_texture_producer(context, rtc, clip, matrixProvider, paint, &tileProducer,
|
draw_texture_producer(context, rtc, clip, matrixProvider, paint, &tileProducer,
|
||||||
tileR, rectToDraw, nullptr, offsetSrcToDst, aa, aaFlags,
|
tileR, rectToDraw, nullptr, offsetSrcToDst, aa, aaFlags,
|
||||||
constraint, wm, fm, doBicubic);
|
constraint, sampler, doBicubic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -650,10 +678,9 @@ void SkGpuDevice::drawImageQuad(const SkImage* image, const SkRect* srcRect, con
|
|||||||
preViewMatrix ? *preViewMatrix : SkMatrix::I());
|
preViewMatrix ? *preViewMatrix : SkMatrix::I());
|
||||||
const SkMatrix& ctm(matrixProvider.localToDevice());
|
const SkMatrix& ctm(matrixProvider.localToDevice());
|
||||||
|
|
||||||
bool doBicubic;
|
bool sharpenMM = fContext->priv().options().fSharpenMipmappedTextures;
|
||||||
GrSamplerState::Filter fm = GrSkFilterQualityToGrFilterMode(
|
auto [fm, mm, bicubic] = GrInterpretFilterQuality(image->dimensions(), paint.getFilterQuality(),
|
||||||
image->width(), image->height(), paint.getFilterQuality(), ctm, srcToDst,
|
ctm, srcToDst, sharpenMM);
|
||||||
fContext->priv().options().fSharpenMipmappedTextures, &doBicubic);
|
|
||||||
|
|
||||||
auto clip = this->clip();
|
auto clip = this->clip();
|
||||||
|
|
||||||
@ -667,7 +694,7 @@ void SkGpuDevice::drawImageQuad(const SkImage* image, const SkRect* srcRect, con
|
|||||||
GrYUVAImageTextureMaker maker(fContext.get(), image);
|
GrYUVAImageTextureMaker maker(fContext.get(), image);
|
||||||
draw_texture_producer(fContext.get(), fRenderTargetContext.get(), clip, matrixProvider,
|
draw_texture_producer(fContext.get(), fRenderTargetContext.get(), clip, matrixProvider,
|
||||||
paint, &maker, src, dst, dstClip, srcToDst, aa, aaFlags, constraint,
|
paint, &maker, src, dst, dstClip, srcToDst, aa, aaFlags, constraint,
|
||||||
wrapMode, fm, doBicubic);
|
{wrapMode, fm, mm}, bicubic);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -691,7 +718,7 @@ void SkGpuDevice::drawImageQuad(const SkImage* image, const SkRect* srcRect, con
|
|||||||
GrTextureAdjuster adjuster(fContext.get(), std::move(view), colorInfo, pinnedUniqueID);
|
GrTextureAdjuster adjuster(fContext.get(), std::move(view), colorInfo, pinnedUniqueID);
|
||||||
draw_texture_producer(fContext.get(), fRenderTargetContext.get(), clip, matrixProvider,
|
draw_texture_producer(fContext.get(), fRenderTargetContext.get(), clip, matrixProvider,
|
||||||
paint, &adjuster, src, dst, dstClip, srcToDst, aa, aaFlags,
|
paint, &adjuster, src, dst, dstClip, srcToDst, aa, aaFlags,
|
||||||
constraint, wrapMode, fm, doBicubic);
|
constraint, {wrapMode, fm, mm}, bicubic);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -701,7 +728,7 @@ void SkGpuDevice::drawImageQuad(const SkImage* image, const SkRect* srcRect, con
|
|||||||
SkASSERT(!image->isTextureBacked());
|
SkASSERT(!image->isTextureBacked());
|
||||||
|
|
||||||
int tileFilterPad;
|
int tileFilterPad;
|
||||||
if (doBicubic) {
|
if (bicubic) {
|
||||||
tileFilterPad = GrBicubicEffect::kFilterTexelPad;
|
tileFilterPad = GrBicubicEffect::kFilterTexelPad;
|
||||||
} else if (GrSamplerState::Filter::kNearest == fm) {
|
} else if (GrSamplerState::Filter::kNearest == fm) {
|
||||||
tileFilterPad = 0;
|
tileFilterPad = 0;
|
||||||
@ -724,7 +751,7 @@ void SkGpuDevice::drawImageQuad(const SkImage* image, const SkRect* srcRect, con
|
|||||||
LogDrawScaleFactor(ctm, srcToDst, paint.getFilterQuality());
|
LogDrawScaleFactor(ctm, srcToDst, paint.getFilterQuality());
|
||||||
draw_tiled_bitmap(fContext.get(), fRenderTargetContext.get(), clip, bm, tileSize,
|
draw_tiled_bitmap(fContext.get(), fRenderTargetContext.get(), clip, bm, tileSize,
|
||||||
matrixProvider, srcToDst, src, clippedSubset, paint, aa,
|
matrixProvider, srcToDst, src, clippedSubset, paint, aa,
|
||||||
constraint, wrapMode, fm, doBicubic);
|
constraint, {wrapMode, fm, mm}, bicubic);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -740,7 +767,7 @@ void SkGpuDevice::drawImageQuad(const SkImage* image, const SkRect* srcRect, con
|
|||||||
GrImageTextureMaker maker(fContext.get(), image, GrImageTexGenPolicy::kDraw);
|
GrImageTextureMaker maker(fContext.get(), image, GrImageTexGenPolicy::kDraw);
|
||||||
draw_texture_producer(fContext.get(), fRenderTargetContext.get(), clip, matrixProvider,
|
draw_texture_producer(fContext.get(), fRenderTargetContext.get(), clip, matrixProvider,
|
||||||
paint, &maker, src, dst, dstClip, srcToDst, aa, aaFlags, constraint,
|
paint, &maker, src, dst, dstClip, srcToDst, aa, aaFlags, constraint,
|
||||||
wrapMode, fm, doBicubic);
|
{wrapMode, fm, mm}, bicubic);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -749,7 +776,7 @@ void SkGpuDevice::drawImageQuad(const SkImage* image, const SkRect* srcRect, con
|
|||||||
GrBitmapTextureMaker maker(fContext.get(), bm, GrImageTexGenPolicy::kDraw);
|
GrBitmapTextureMaker maker(fContext.get(), bm, GrImageTexGenPolicy::kDraw);
|
||||||
draw_texture_producer(fContext.get(), fRenderTargetContext.get(), clip, matrixProvider,
|
draw_texture_producer(fContext.get(), fRenderTargetContext.get(), clip, matrixProvider,
|
||||||
paint, &maker, src, dst, dstClip, srcToDst, aa, aaFlags, constraint,
|
paint, &maker, src, dst, dstClip, srcToDst, aa, aaFlags, constraint,
|
||||||
wrapMode, fm, doBicubic);
|
{wrapMode, fm, mm}, bicubic);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise don't know how to draw it
|
// Otherwise don't know how to draw it
|
||||||
@ -799,9 +826,17 @@ void SkGpuDevice::drawEdgeAAImageSet(const SkCanvas::ImageSetEntry set[], int co
|
|||||||
auto textureXform = GrColorSpaceXform::Make(
|
auto textureXform = GrColorSpaceXform::Make(
|
||||||
set[base].fImage->colorSpace(), set[base].fImage->alphaType(),
|
set[base].fImage->colorSpace(), set[base].fImage->alphaType(),
|
||||||
fRenderTargetContext->colorInfo().colorSpace(), kPremul_SkAlphaType);
|
fRenderTargetContext->colorInfo().colorSpace(), kPremul_SkAlphaType);
|
||||||
fRenderTargetContext->drawTextureSet(this->clip(), textures.get() + base, n, p,
|
fRenderTargetContext->drawTextureSet(this->clip(),
|
||||||
filter, mode, GrAA::kYes, constraint,
|
textures.get() + base,
|
||||||
this->localToDevice(), std::move(textureXform));
|
n,
|
||||||
|
p,
|
||||||
|
filter,
|
||||||
|
GrSamplerState::MipmapMode::kNone,
|
||||||
|
mode,
|
||||||
|
GrAA::kYes,
|
||||||
|
constraint,
|
||||||
|
this->localToDevice(),
|
||||||
|
std::move(textureXform));
|
||||||
}
|
}
|
||||||
base = nextBase;
|
base = nextBase;
|
||||||
n = 0;
|
n = 0;
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "src/core/SkColorSpacePriv.h"
|
#include "src/core/SkColorSpacePriv.h"
|
||||||
#include "src/core/SkImagePriv.h"
|
#include "src/core/SkImagePriv.h"
|
||||||
#include "src/core/SkMaskFilterBase.h"
|
#include "src/core/SkMaskFilterBase.h"
|
||||||
|
#include "src/core/SkMatrixPriv.h"
|
||||||
#include "src/core/SkMessageBus.h"
|
#include "src/core/SkMessageBus.h"
|
||||||
#include "src/core/SkMipmap.h"
|
#include "src/core/SkMipmap.h"
|
||||||
#include "src/core/SkPaintPriv.h"
|
#include "src/core/SkPaintPriv.h"
|
||||||
@ -37,6 +38,7 @@
|
|||||||
#include "src/gpu/GrRecordingContextPriv.h"
|
#include "src/gpu/GrRecordingContextPriv.h"
|
||||||
#include "src/gpu/GrTextureProxy.h"
|
#include "src/gpu/GrTextureProxy.h"
|
||||||
#include "src/gpu/GrXferProcessor.h"
|
#include "src/gpu/GrXferProcessor.h"
|
||||||
|
#include "src/gpu/SkGr.h"
|
||||||
#include "src/gpu/effects/GrBicubicEffect.h"
|
#include "src/gpu/effects/GrBicubicEffect.h"
|
||||||
#include "src/gpu/effects/GrPorterDuffXferProcessor.h"
|
#include "src/gpu/effects/GrPorterDuffXferProcessor.h"
|
||||||
#include "src/gpu/effects/GrXfermodeFragmentProcessor.h"
|
#include "src/gpu/effects/GrXfermodeFragmentProcessor.h"
|
||||||
@ -432,21 +434,25 @@ bool SkPaintToGrPaintWithTexture(GrRecordingContext* context,
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
GrSamplerState::Filter GrSkFilterQualityToGrFilterMode(int imageWidth, int imageHeight,
|
std::tuple<GrSamplerState::Filter,
|
||||||
SkFilterQuality paintFilterQuality,
|
GrSamplerState::MipmapMode,
|
||||||
const SkMatrix& viewM,
|
bool /*bicubic*/>
|
||||||
const SkMatrix& localM,
|
GrInterpretFilterQuality(SkISize imageDims,
|
||||||
bool sharpenMipmappedTextures,
|
SkFilterQuality paintFilterQuality,
|
||||||
bool* doBicubic) {
|
const SkMatrix& viewM,
|
||||||
*doBicubic = false;
|
const SkMatrix& localM,
|
||||||
if (imageWidth <= 1 && imageHeight <= 1) {
|
bool sharpenMipmappedTextures) {
|
||||||
return GrSamplerState::Filter::kNearest;
|
using Filter = GrSamplerState::Filter;
|
||||||
|
using MipmapMode = GrSamplerState::MipmapMode;
|
||||||
|
if (imageDims.area() <= 1) {
|
||||||
|
// TOOD: should know we're not in decal mode to do this transformation.
|
||||||
|
return {Filter::kNearest, MipmapMode::kNone, false};
|
||||||
}
|
}
|
||||||
switch (paintFilterQuality) {
|
switch (paintFilterQuality) {
|
||||||
case kNone_SkFilterQuality:
|
case kNone_SkFilterQuality:
|
||||||
return GrSamplerState::Filter::kNearest;
|
return {Filter::kNearest, MipmapMode::kNone, false};
|
||||||
case kLow_SkFilterQuality:
|
case kLow_SkFilterQuality:
|
||||||
return GrSamplerState::Filter::kLinear;
|
return {Filter::kLinear, MipmapMode::kNone, false};
|
||||||
case kMedium_SkFilterQuality: {
|
case kMedium_SkFilterQuality: {
|
||||||
SkMatrix matrix;
|
SkMatrix matrix;
|
||||||
matrix.setConcat(viewM, localM);
|
matrix.setConcat(viewM, localM);
|
||||||
@ -460,18 +466,21 @@ GrSamplerState::Filter GrSkFilterQualityToGrFilterMode(int imageWidth, int image
|
|||||||
// 2^0.5/2 = s
|
// 2^0.5/2 = s
|
||||||
SkScalar mipScale = sharpenMipmappedTextures ? SK_ScalarRoot2Over2 : SK_Scalar1;
|
SkScalar mipScale = sharpenMipmappedTextures ? SK_ScalarRoot2Over2 : SK_Scalar1;
|
||||||
if (matrix.getMinScale() < mipScale) {
|
if (matrix.getMinScale() < mipScale) {
|
||||||
return GrSamplerState::Filter::kMipMap;
|
return {Filter::kLinear, MipmapMode::kLinear, false};
|
||||||
} else {
|
} else {
|
||||||
// Don't trigger MIP level generation unnecessarily.
|
return {Filter::kLinear, MipmapMode::kNone, false};
|
||||||
return GrSamplerState::Filter::kLinear;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case kHigh_SkFilterQuality: {
|
case kHigh_SkFilterQuality: {
|
||||||
SkMatrix matrix;
|
SkMatrix matrix;
|
||||||
matrix.setConcat(viewM, localM);
|
matrix.setConcat(viewM, localM);
|
||||||
GrSamplerState::Filter textureFilterMode;
|
switch (SkMatrixPriv::AdjustHighQualityFilterLevel(matrix)) {
|
||||||
*doBicubic = GrBicubicEffect::ShouldUseBicubic(matrix, &textureFilterMode);
|
case kNone_SkFilterQuality: return {Filter::kNearest, MipmapMode::kNone , false};
|
||||||
return textureFilterMode;
|
case kLow_SkFilterQuality: return {Filter::kLinear , MipmapMode::kNone , false};
|
||||||
|
case kMedium_SkFilterQuality: return {Filter::kLinear , MipmapMode::kLinear, false};
|
||||||
|
case kHigh_SkFilterQuality: return {Filter::kNearest, MipmapMode::kNone , true };
|
||||||
|
}
|
||||||
|
SkUNREACHABLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SkUNREACHABLE;
|
SkUNREACHABLE;
|
||||||
|
@ -141,12 +141,19 @@ bool SkPaintToGrPaintWithTexture(GrRecordingContext*,
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Misc Sk to Gr type conversions
|
// Misc Sk to Gr type conversions
|
||||||
|
|
||||||
GrSamplerState::Filter GrSkFilterQualityToGrFilterMode(int imageWidth, int imageHeight,
|
/**
|
||||||
SkFilterQuality paintFilterQuality,
|
* Determines how to interpret SkFilterQuality given draw params and canvas state. If the returned
|
||||||
const SkMatrix& viewM,
|
* bool is true then bicubic filtering should be used (and the two other return values can be
|
||||||
const SkMatrix& localM,
|
* ignored).
|
||||||
bool sharpenMipmappedTextures,
|
*/
|
||||||
bool* doBicubic);
|
std::tuple<GrSamplerState::Filter,
|
||||||
|
GrSamplerState::MipmapMode,
|
||||||
|
bool /*bicubic*/>
|
||||||
|
GrInterpretFilterQuality(SkISize imageDims,
|
||||||
|
SkFilterQuality paintFilterQuality,
|
||||||
|
const SkMatrix& viewM,
|
||||||
|
const SkMatrix& localM,
|
||||||
|
bool sharpenMipmappedTextures);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -128,6 +128,24 @@ static D3D12_TEXTURE_ADDRESS_MODE wrap_mode_to_d3d_address_mode(GrSamplerState::
|
|||||||
SK_ABORT("Unknown wrap mode.");
|
SK_ABORT("Unknown wrap mode.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static D3D12_FILTER d3d_filter(GrSamplerState sampler) {
|
||||||
|
switch (sampler.mipmapMode()) {
|
||||||
|
case GrSamplerState::MipmapMode::kNone:
|
||||||
|
switch (sampler.filter()) {
|
||||||
|
case GrSamplerState::Filter::kNearest: return D3D12_FILTER_MIN_MAG_MIP_POINT;
|
||||||
|
case GrSamplerState::Filter::kLinear: return D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT;
|
||||||
|
}
|
||||||
|
SkUNREACHABLE;
|
||||||
|
case GrSamplerState::MipmapMode::kLinear:
|
||||||
|
switch (sampler.filter()) {
|
||||||
|
case GrSamplerState::Filter::kNearest: return D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR;
|
||||||
|
case GrSamplerState::Filter::kLinear: return D3D12_FILTER_MIN_MAG_MIP_LINEAR;
|
||||||
|
}
|
||||||
|
SkUNREACHABLE;
|
||||||
|
}
|
||||||
|
SkUNREACHABLE;
|
||||||
|
}
|
||||||
|
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE GrD3DResourceProvider::findOrCreateCompatibleSampler(
|
D3D12_CPU_DESCRIPTOR_HANDLE GrD3DResourceProvider::findOrCreateCompatibleSampler(
|
||||||
const GrSamplerState& params) {
|
const GrSamplerState& params) {
|
||||||
uint32_t key = params.asIndex();
|
uint32_t key = params.asIndex();
|
||||||
@ -136,17 +154,7 @@ D3D12_CPU_DESCRIPTOR_HANDLE GrD3DResourceProvider::findOrCreateCompatibleSampler
|
|||||||
return *samplerPtr;
|
return *samplerPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static D3D12_FILTER d3dFilterModes[] = {
|
D3D12_FILTER filter = d3d_filter(params);
|
||||||
D3D12_FILTER_MIN_MAG_MIP_POINT,
|
|
||||||
D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT,
|
|
||||||
D3D12_FILTER_MIN_MAG_MIP_LINEAR
|
|
||||||
};
|
|
||||||
|
|
||||||
static_assert((int)GrSamplerState::Filter::kNearest == 0);
|
|
||||||
static_assert((int)GrSamplerState::Filter::kLinear == 1);
|
|
||||||
static_assert((int)GrSamplerState::Filter::kMipMap == 2);
|
|
||||||
|
|
||||||
D3D12_FILTER filter = d3dFilterModes[static_cast<int>(params.filter())];
|
|
||||||
D3D12_TEXTURE_ADDRESS_MODE addressModeU = wrap_mode_to_d3d_address_mode(params.wrapModeX());
|
D3D12_TEXTURE_ADDRESS_MODE addressModeU = wrap_mode_to_d3d_address_mode(params.wrapModeX());
|
||||||
D3D12_TEXTURE_ADDRESS_MODE addressModeV = wrap_mode_to_d3d_address_mode(params.wrapModeY());
|
D3D12_TEXTURE_ADDRESS_MODE addressModeV = wrap_mode_to_d3d_address_mode(params.wrapModeY());
|
||||||
|
|
||||||
|
@ -73,7 +73,6 @@ static wgpu::FilterMode to_dawn_filter_mode(GrSamplerState::Filter filter) {
|
|||||||
case GrSamplerState::Filter::kNearest:
|
case GrSamplerState::Filter::kNearest:
|
||||||
return wgpu::FilterMode::Nearest;
|
return wgpu::FilterMode::Nearest;
|
||||||
case GrSamplerState::Filter::kLinear:
|
case GrSamplerState::Filter::kLinear:
|
||||||
case GrSamplerState::Filter::kMipMap:
|
|
||||||
return wgpu::FilterMode::Linear;
|
return wgpu::FilterMode::Linear;
|
||||||
default:
|
default:
|
||||||
SkASSERT(!"unsupported filter mode");
|
SkASSERT(!"unsupported filter mode");
|
||||||
|
@ -329,25 +329,3 @@ std::unique_ptr<GrFragmentProcessor> GrBicubicEffect::TestCreate(GrProcessorTest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
bool GrBicubicEffect::ShouldUseBicubic(const SkMatrix& matrix, GrSamplerState::Filter* filterMode) {
|
|
||||||
switch (SkMatrixPriv::AdjustHighQualityFilterLevel(matrix)) {
|
|
||||||
case kNone_SkFilterQuality:
|
|
||||||
*filterMode = GrSamplerState::Filter::kNearest;
|
|
||||||
break;
|
|
||||||
case kLow_SkFilterQuality:
|
|
||||||
*filterMode = GrSamplerState::Filter::kLinear;
|
|
||||||
break;
|
|
||||||
case kMedium_SkFilterQuality:
|
|
||||||
*filterMode = GrSamplerState::Filter::kMipMap;
|
|
||||||
break;
|
|
||||||
case kHigh_SkFilterQuality:
|
|
||||||
// When we use the bicubic filtering effect each sample is read from the texture using
|
|
||||||
// nearest neighbor sampling.
|
|
||||||
*filterMode = GrSamplerState::Filter::kNearest;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
@ -99,16 +99,6 @@ public:
|
|||||||
Kernel,
|
Kernel,
|
||||||
Direction);
|
Direction);
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines whether the bicubic effect should be used based on the transformation from the
|
|
||||||
* local coords to the device. Returns true if the bicubic effect should be used. filterMode
|
|
||||||
* is set to appropriate filtering mode to use regardless of the return result (e.g. when this
|
|
||||||
* returns false it may indicate that the best fallback is to use kMipMap, kLinear, or
|
|
||||||
* kNearest).
|
|
||||||
*/
|
|
||||||
static bool ShouldUseBicubic(const SkMatrix& localCoordsToDevice,
|
|
||||||
GrSamplerState::Filter* filterMode);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Impl;
|
class Impl;
|
||||||
|
|
||||||
|
@ -15,8 +15,9 @@
|
|||||||
#include "src/sksl/SkSLCPP.h"
|
#include "src/sksl/SkSLCPP.h"
|
||||||
#include "src/sksl/SkSLUtil.h"
|
#include "src/sksl/SkSLUtil.h"
|
||||||
|
|
||||||
using Mode = GrSamplerState::WrapMode;
|
using Wrap = GrSamplerState::WrapMode;
|
||||||
using Filter = GrSamplerState::Filter;
|
using Filter = GrSamplerState::Filter;
|
||||||
|
using MipmapMode = GrSamplerState::MipmapMode;
|
||||||
|
|
||||||
struct GrTextureEffect::Sampling {
|
struct GrTextureEffect::Sampling {
|
||||||
GrSamplerState fHWSampler;
|
GrSamplerState fHWSampler;
|
||||||
@ -24,9 +25,9 @@ struct GrTextureEffect::Sampling {
|
|||||||
SkRect fShaderSubset = {0, 0, 0, 0};
|
SkRect fShaderSubset = {0, 0, 0, 0};
|
||||||
SkRect fShaderClamp = {0, 0, 0, 0};
|
SkRect fShaderClamp = {0, 0, 0, 0};
|
||||||
float fBorder[4] = {0, 0, 0, 0};
|
float fBorder[4] = {0, 0, 0, 0};
|
||||||
Sampling(GrSamplerState::Filter filter) : fHWSampler(filter) {}
|
Sampling(Filter filter, MipmapMode mm) : fHWSampler(filter, mm) {}
|
||||||
Sampling(const GrSurfaceProxy& proxy,
|
Sampling(const GrSurfaceProxy& proxy,
|
||||||
GrSamplerState sampler,
|
GrSamplerState wrap,
|
||||||
const SkRect&,
|
const SkRect&,
|
||||||
const SkRect*,
|
const SkRect*,
|
||||||
const float border[4],
|
const float border[4],
|
||||||
@ -59,28 +60,29 @@ GrTextureEffect::Sampling::Sampling(const GrSurfaceProxy& proxy,
|
|||||||
ShaderMode fShaderMode;
|
ShaderMode fShaderMode;
|
||||||
Span fShaderSubset;
|
Span fShaderSubset;
|
||||||
Span fShaderClamp;
|
Span fShaderClamp;
|
||||||
Mode fHWMode;
|
Wrap fHWWrap;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto type = proxy.asTextureProxy()->textureType();
|
auto type = proxy.asTextureProxy()->textureType();
|
||||||
auto filter = sampler.filter();
|
auto filter = sampler.filter();
|
||||||
|
auto mm = sampler.mipmapMode();
|
||||||
|
|
||||||
auto resolve = [&](int size, Mode mode, Span subset, Span domain, float linearFilterInset) {
|
auto resolve = [&](int size, Wrap wrap, Span subset, Span domain, float linearFilterInset) {
|
||||||
Result1D r;
|
Result1D r;
|
||||||
bool canDoModeInHW = true;
|
bool canDoModeInHW = true;
|
||||||
// TODO: Use HW border color when available.
|
// TODO: Use HW border color when available.
|
||||||
if (mode == Mode::kClampToBorder &&
|
if (wrap == Wrap::kClampToBorder &&
|
||||||
(!caps.clampToBorderSupport() || border[0] || border[1] || border[2] || border[3])) {
|
(!caps.clampToBorderSupport() || border[0] || border[1] || border[2] || border[3])) {
|
||||||
canDoModeInHW = false;
|
canDoModeInHW = false;
|
||||||
} else if (mode != Mode::kClamp && !caps.npotTextureTileSupport() && !SkIsPow2(size)) {
|
} else if (wrap != Wrap::kClamp && !caps.npotTextureTileSupport() && !SkIsPow2(size)) {
|
||||||
canDoModeInHW = false;
|
canDoModeInHW = false;
|
||||||
} else if (type != GrTextureType::k2D &&
|
} else if (type != GrTextureType::k2D &&
|
||||||
!(mode == Mode::kClamp || mode == Mode::kClampToBorder)) {
|
!(wrap == Wrap::kClamp || wrap == Wrap::kClampToBorder)) {
|
||||||
canDoModeInHW = false;
|
canDoModeInHW = false;
|
||||||
}
|
}
|
||||||
if (canDoModeInHW && size > 0 && subset.fA <= 0 && subset.fB >= size) {
|
if (canDoModeInHW && size > 0 && subset.fA <= 0 && subset.fB >= size) {
|
||||||
r.fShaderMode = ShaderMode::kNone;
|
r.fShaderMode = ShaderMode::kNone;
|
||||||
r.fHWMode = mode;
|
r.fHWWrap = wrap;
|
||||||
r.fShaderSubset = r.fShaderClamp = {0, 0};
|
r.fShaderSubset = r.fShaderClamp = {0, 0};
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -107,12 +109,12 @@ GrTextureEffect::Sampling::Sampling(const GrSurfaceProxy& proxy,
|
|||||||
// So the wrap mode effectively doesn't matter. We use kClamp since it is always
|
// So the wrap mode effectively doesn't matter. We use kClamp since it is always
|
||||||
// supported.
|
// supported.
|
||||||
r.fShaderMode = ShaderMode::kNone;
|
r.fShaderMode = ShaderMode::kNone;
|
||||||
r.fHWMode = Mode::kClamp;
|
r.fHWWrap = Wrap::kClamp;
|
||||||
r.fShaderSubset = r.fShaderClamp = {0, 0};
|
r.fShaderSubset = r.fShaderClamp = {0, 0};
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
r.fShaderMode = GetShaderMode(mode, filter);
|
r.fShaderMode = GetShaderMode(wrap, filter, mm);
|
||||||
r.fHWMode = Mode::kClamp;
|
r.fHWWrap = Wrap::kClamp;
|
||||||
return r;
|
return r;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -128,7 +130,7 @@ GrTextureEffect::Sampling::Sampling(const GrSurfaceProxy& proxy,
|
|||||||
: Span{SK_FloatNegativeInfinity, SK_FloatInfinity};
|
: Span{SK_FloatNegativeInfinity, SK_FloatInfinity};
|
||||||
auto y = resolve(dim.height(), sampler.wrapModeY(), subsetY, domainY, linearFilterInset.fY);
|
auto y = resolve(dim.height(), sampler.wrapModeY(), subsetY, domainY, linearFilterInset.fY);
|
||||||
|
|
||||||
fHWSampler = {x.fHWMode, y.fHWMode, filter};
|
fHWSampler = {x.fHWWrap, y.fHWWrap, filter, mm};
|
||||||
fShaderModes[0] = x.fShaderMode;
|
fShaderModes[0] = x.fShaderMode;
|
||||||
fShaderModes[1] = y.fShaderMode;
|
fShaderModes[1] = y.fShaderMode;
|
||||||
fShaderSubset = {x.fShaderSubset.fA, y.fShaderSubset.fA,
|
fShaderSubset = {x.fShaderSubset.fA, y.fShaderSubset.fA,
|
||||||
@ -139,8 +141,8 @@ GrTextureEffect::Sampling::Sampling(const GrSurfaceProxy& proxy,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool GrTextureEffect::Sampling::hasBorderAlpha() const {
|
bool GrTextureEffect::Sampling::hasBorderAlpha() const {
|
||||||
if (fHWSampler.wrapModeX() == GrSamplerState::WrapMode::kClampToBorder ||
|
if (fHWSampler.wrapModeX() == Wrap::kClampToBorder ||
|
||||||
fHWSampler.wrapModeY() == GrSamplerState::WrapMode::kClampToBorder) {
|
fHWSampler.wrapModeY() == Wrap::kClampToBorder) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (ShaderModeIsClampToBorder(fShaderModes[0]) || ShaderModeIsClampToBorder(fShaderModes[1])) {
|
if (ShaderModeIsClampToBorder(fShaderModes[0]) || ShaderModeIsClampToBorder(fShaderModes[1])) {
|
||||||
@ -192,14 +194,15 @@ static void get_matrix(const SkMatrix& preMatrix, const GrSurfaceProxyView& view
|
|||||||
std::unique_ptr<GrFragmentProcessor> GrTextureEffect::Make(GrSurfaceProxyView view,
|
std::unique_ptr<GrFragmentProcessor> GrTextureEffect::Make(GrSurfaceProxyView view,
|
||||||
SkAlphaType alphaType,
|
SkAlphaType alphaType,
|
||||||
const SkMatrix& matrix,
|
const SkMatrix& matrix,
|
||||||
Filter filter) {
|
Filter filter,
|
||||||
|
MipmapMode mm) {
|
||||||
SkMatrix final;
|
SkMatrix final;
|
||||||
bool lazyProxyNormalization;
|
bool lazyProxyNormalization;
|
||||||
get_matrix(matrix, view, &final, &lazyProxyNormalization);
|
get_matrix(matrix, view, &final, &lazyProxyNormalization);
|
||||||
return GrMatrixEffect::Make(final, std::unique_ptr<GrFragmentProcessor>(
|
return GrMatrixEffect::Make(final, std::unique_ptr<GrFragmentProcessor>(
|
||||||
new GrTextureEffect(std::move(view),
|
new GrTextureEffect(std::move(view),
|
||||||
alphaType,
|
alphaType,
|
||||||
Sampling(filter),
|
Sampling(filter, mm),
|
||||||
lazyProxyNormalization)));
|
lazyProxyNormalization)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,14 +265,14 @@ std::unique_ptr<GrFragmentProcessor> GrTextureEffect::MakeCustomLinearFilterInse
|
|||||||
GrSurfaceProxyView view,
|
GrSurfaceProxyView view,
|
||||||
SkAlphaType alphaType,
|
SkAlphaType alphaType,
|
||||||
const SkMatrix& matrix,
|
const SkMatrix& matrix,
|
||||||
GrSamplerState::WrapMode wx,
|
Wrap wx,
|
||||||
GrSamplerState::WrapMode wy,
|
Wrap wy,
|
||||||
const SkRect& subset,
|
const SkRect& subset,
|
||||||
const SkRect* domain,
|
const SkRect* domain,
|
||||||
SkVector inset,
|
SkVector inset,
|
||||||
const GrCaps& caps,
|
const GrCaps& caps,
|
||||||
const float border[4]) {
|
const float border[4]) {
|
||||||
GrSamplerState sampler(wx, wy, GrSamplerState::Filter::kLinear);
|
GrSamplerState sampler(wx, wy, Filter::kLinear);
|
||||||
Sampling sampling(*view.proxy(), sampler, subset, domain, border, caps, inset);
|
Sampling sampling(*view.proxy(), sampler, subset, domain, border, caps, inset);
|
||||||
SkMatrix final;
|
SkMatrix final;
|
||||||
bool lazyProxyNormalization;
|
bool lazyProxyNormalization;
|
||||||
@ -279,32 +282,39 @@ std::unique_ptr<GrFragmentProcessor> GrTextureEffect::MakeCustomLinearFilterInse
|
|||||||
std::move(view), alphaType, sampling, lazyProxyNormalization)));
|
std::move(view), alphaType, sampling, lazyProxyNormalization)));
|
||||||
}
|
}
|
||||||
|
|
||||||
GrTextureEffect::ShaderMode GrTextureEffect::GetShaderMode(GrSamplerState::WrapMode mode,
|
GrTextureEffect::ShaderMode GrTextureEffect::GetShaderMode(Wrap wrap,
|
||||||
GrSamplerState::Filter filter) {
|
Filter filter,
|
||||||
switch (mode) {
|
MipmapMode mm) {
|
||||||
case GrSamplerState::WrapMode::kMirrorRepeat:
|
switch (wrap) {
|
||||||
|
case Wrap::kMirrorRepeat:
|
||||||
return ShaderMode::kMirrorRepeat;
|
return ShaderMode::kMirrorRepeat;
|
||||||
case GrSamplerState::WrapMode::kClamp:
|
case Wrap::kClamp:
|
||||||
return ShaderMode::kClamp;
|
return ShaderMode::kClamp;
|
||||||
case GrSamplerState::WrapMode::kRepeat:
|
case Wrap::kRepeat:
|
||||||
switch (filter) {
|
switch (mm) {
|
||||||
case GrSamplerState::Filter::kNearest:
|
case MipmapMode::kNone:
|
||||||
return ShaderMode::kRepeatNearest;
|
switch (filter) {
|
||||||
case GrSamplerState::Filter::kLinear:
|
case Filter::kNearest: return ShaderMode::kRepeat_Nearest_None;
|
||||||
return ShaderMode::kRepeatLinear;
|
case Filter::kLinear: return ShaderMode::kRepeat_Linear_None;
|
||||||
case GrSamplerState::Filter::kMipMap:
|
}
|
||||||
return ShaderMode::kRepeatMipMap;
|
SkUNREACHABLE;
|
||||||
|
case MipmapMode::kLinear:
|
||||||
|
switch (filter) {
|
||||||
|
case Filter::kNearest: return ShaderMode::kRepeat_Nearest_Mipmap;
|
||||||
|
case Filter::kLinear: return ShaderMode::kRepeat_Linear_Mipmap;
|
||||||
|
}
|
||||||
|
SkUNREACHABLE;
|
||||||
}
|
}
|
||||||
SkUNREACHABLE;
|
SkUNREACHABLE;
|
||||||
case GrSamplerState::WrapMode::kClampToBorder:
|
case Wrap::kClampToBorder:
|
||||||
return filter == GrSamplerState::Filter::kNearest ? ShaderMode::kClampToBorderNearest
|
return filter == Filter::kNearest ? ShaderMode::kClampToBorder_Nearest
|
||||||
: ShaderMode::kClampToBorderFilter;
|
: ShaderMode::kClampToBorder_Filter;
|
||||||
}
|
}
|
||||||
SkUNREACHABLE;
|
SkUNREACHABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool GrTextureEffect::ShaderModeIsClampToBorder(ShaderMode m) {
|
inline bool GrTextureEffect::ShaderModeIsClampToBorder(ShaderMode m) {
|
||||||
return m == ShaderMode::kClampToBorderNearest || m == ShaderMode::kClampToBorderFilter;
|
return m == ShaderMode::kClampToBorder_Nearest || m == ShaderMode::kClampToBorder_Filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrTextureEffect::Impl::emitCode(EmitArgs& args) {
|
void GrTextureEffect::Impl::emitCode(EmitArgs& args) {
|
||||||
@ -366,12 +376,13 @@ void GrTextureEffect::Impl::emitCode(EmitArgs& args) {
|
|||||||
switch (m) {
|
switch (m) {
|
||||||
case ShaderMode::kNone: return false;
|
case ShaderMode::kNone: return false;
|
||||||
case ShaderMode::kClamp: return false;
|
case ShaderMode::kClamp: return false;
|
||||||
case ShaderMode::kRepeatNearest: return true;
|
case ShaderMode::kRepeat_Nearest_None: return true;
|
||||||
case ShaderMode::kRepeatLinear: return true;
|
case ShaderMode::kRepeat_Linear_None: return true;
|
||||||
case ShaderMode::kRepeatMipMap: return true;
|
case ShaderMode::kRepeat_Nearest_Mipmap: return true;
|
||||||
|
case ShaderMode::kRepeat_Linear_Mipmap: return true;
|
||||||
case ShaderMode::kMirrorRepeat: return true;
|
case ShaderMode::kMirrorRepeat: return true;
|
||||||
case ShaderMode::kClampToBorderNearest: return true;
|
case ShaderMode::kClampToBorder_Nearest: return true;
|
||||||
case ShaderMode::kClampToBorderFilter: return true;
|
case ShaderMode::kClampToBorder_Filter: return true;
|
||||||
}
|
}
|
||||||
SkUNREACHABLE;
|
SkUNREACHABLE;
|
||||||
};
|
};
|
||||||
@ -380,12 +391,13 @@ void GrTextureEffect::Impl::emitCode(EmitArgs& args) {
|
|||||||
switch (m) {
|
switch (m) {
|
||||||
case ShaderMode::kNone: return false;
|
case ShaderMode::kNone: return false;
|
||||||
case ShaderMode::kClamp: return true;
|
case ShaderMode::kClamp: return true;
|
||||||
case ShaderMode::kRepeatNearest: return true;
|
case ShaderMode::kRepeat_Nearest_None: return true;
|
||||||
case ShaderMode::kRepeatLinear: return true;
|
case ShaderMode::kRepeat_Linear_None: return true;
|
||||||
case ShaderMode::kRepeatMipMap: return true;
|
case ShaderMode::kRepeat_Nearest_Mipmap: return true;
|
||||||
|
case ShaderMode::kRepeat_Linear_Mipmap: return true;
|
||||||
case ShaderMode::kMirrorRepeat: return true;
|
case ShaderMode::kMirrorRepeat: return true;
|
||||||
case ShaderMode::kClampToBorderNearest: return false;
|
case ShaderMode::kClampToBorder_Nearest: return false;
|
||||||
case ShaderMode::kClampToBorderFilter: return true;
|
case ShaderMode::kClampToBorder_Filter: return true;
|
||||||
}
|
}
|
||||||
SkUNREACHABLE;
|
SkUNREACHABLE;
|
||||||
};
|
};
|
||||||
@ -397,12 +409,13 @@ void GrTextureEffect::Impl::emitCode(EmitArgs& args) {
|
|||||||
switch (m) {
|
switch (m) {
|
||||||
case ShaderMode::kNone: return false;
|
case ShaderMode::kNone: return false;
|
||||||
case ShaderMode::kClamp: return false;
|
case ShaderMode::kClamp: return false;
|
||||||
case ShaderMode::kRepeatNearest: return false;
|
case ShaderMode::kRepeat_Nearest_None: return false;
|
||||||
case ShaderMode::kRepeatLinear: return true;
|
case ShaderMode::kRepeat_Linear_None: return true;
|
||||||
case ShaderMode::kRepeatMipMap: return true;
|
case ShaderMode::kRepeat_Nearest_Mipmap: return true;
|
||||||
|
case ShaderMode::kRepeat_Linear_Mipmap: return true;
|
||||||
case ShaderMode::kMirrorRepeat: return false;
|
case ShaderMode::kMirrorRepeat: return false;
|
||||||
case ShaderMode::kClampToBorderNearest: return true;
|
case ShaderMode::kClampToBorder_Nearest: return true;
|
||||||
case ShaderMode::kClampToBorderFilter: return true;
|
case ShaderMode::kClampToBorder_Filter: return true;
|
||||||
}
|
}
|
||||||
SkUNREACHABLE;
|
SkUNREACHABLE;
|
||||||
};
|
};
|
||||||
@ -458,13 +471,13 @@ void GrTextureEffect::Impl::emitCode(EmitArgs& args) {
|
|||||||
// These modes either don't use the subset rect or don't need to map the
|
// These modes either don't use the subset rect or don't need to map the
|
||||||
// coords to be within the subset.
|
// coords to be within the subset.
|
||||||
case ShaderMode::kNone:
|
case ShaderMode::kNone:
|
||||||
case ShaderMode::kClampToBorderNearest:
|
case ShaderMode::kClampToBorder_Nearest:
|
||||||
case ShaderMode::kClampToBorderFilter:
|
case ShaderMode::kClampToBorder_Filter:
|
||||||
case ShaderMode::kClamp:
|
case ShaderMode::kClamp:
|
||||||
fb->codeAppendf("subsetCoord.%s = inCoord.%s;", coordSwizzle, coordSwizzle);
|
fb->codeAppendf("subsetCoord.%s = inCoord.%s;", coordSwizzle, coordSwizzle);
|
||||||
break;
|
break;
|
||||||
case ShaderMode::kRepeatNearest:
|
case ShaderMode::kRepeat_Nearest_None:
|
||||||
case ShaderMode::kRepeatLinear:
|
case ShaderMode::kRepeat_Linear_None:
|
||||||
fb->codeAppendf(
|
fb->codeAppendf(
|
||||||
"subsetCoord.%s = mod(inCoord.%s - %s.%s, %s.%s - %s.%s) + "
|
"subsetCoord.%s = mod(inCoord.%s - %s.%s, %s.%s - %s.%s) + "
|
||||||
"%s.%s;",
|
"%s.%s;",
|
||||||
@ -472,7 +485,8 @@ void GrTextureEffect::Impl::emitCode(EmitArgs& args) {
|
|||||||
subsetStopSwizzle, subsetName, subsetStartSwizzle, subsetName,
|
subsetStopSwizzle, subsetName, subsetStartSwizzle, subsetName,
|
||||||
subsetStartSwizzle);
|
subsetStartSwizzle);
|
||||||
break;
|
break;
|
||||||
case ShaderMode::kRepeatMipMap:
|
case ShaderMode::kRepeat_Nearest_Mipmap:
|
||||||
|
case ShaderMode::kRepeat_Linear_Mipmap:
|
||||||
// The approach here is to generate two sets of texture coords that
|
// The approach here is to generate two sets of texture coords that
|
||||||
// are both "moving" at the same speed (if not direction) as
|
// are both "moving" at the same speed (if not direction) as
|
||||||
// inCoords. We accomplish that by using two out of phase mirror
|
// inCoords. We accomplish that by using two out of phase mirror
|
||||||
@ -533,17 +547,23 @@ void GrTextureEffect::Impl::emitCode(EmitArgs& args) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Insert vars for extra coords and blending weights for kRepeatMipMap.
|
// Insert vars for extra coords and blending weights for repeat + mip map.
|
||||||
const char* extraRepeatCoordX = nullptr;
|
const char* extraRepeatCoordX = nullptr;
|
||||||
const char* repeatCoordWeightX = nullptr;
|
const char* repeatCoordWeightX = nullptr;
|
||||||
const char* extraRepeatCoordY = nullptr;
|
const char* extraRepeatCoordY = nullptr;
|
||||||
const char* repeatCoordWeightY = nullptr;
|
const char* repeatCoordWeightY = nullptr;
|
||||||
if (m[0] == ShaderMode::kRepeatMipMap) {
|
|
||||||
|
bool mipmapRepeatX = m[0] == ShaderMode::kRepeat_Nearest_Mipmap ||
|
||||||
|
m[0] == ShaderMode::kRepeat_Linear_Mipmap;
|
||||||
|
bool mipmapRepeatY = m[1] == ShaderMode::kRepeat_Nearest_Mipmap ||
|
||||||
|
m[1] == ShaderMode::kRepeat_Linear_Mipmap;
|
||||||
|
|
||||||
|
if (mipmapRepeatX) {
|
||||||
fb->codeAppend("float extraRepeatCoordX; half repeatCoordWeightX;");
|
fb->codeAppend("float extraRepeatCoordX; half repeatCoordWeightX;");
|
||||||
extraRepeatCoordX = "extraRepeatCoordX";
|
extraRepeatCoordX = "extraRepeatCoordX";
|
||||||
repeatCoordWeightX = "repeatCoordWeightX";
|
repeatCoordWeightX = "repeatCoordWeightX";
|
||||||
}
|
}
|
||||||
if (m[1] == ShaderMode::kRepeatMipMap) {
|
if (mipmapRepeatY) {
|
||||||
fb->codeAppend("float extraRepeatCoordY; half repeatCoordWeightY;");
|
fb->codeAppend("float extraRepeatCoordY; half repeatCoordWeightY;");
|
||||||
extraRepeatCoordY = "extraRepeatCoordY";
|
extraRepeatCoordY = "extraRepeatCoordY";
|
||||||
repeatCoordWeightY = "repeatCoordWeightY";
|
repeatCoordWeightY = "repeatCoordWeightY";
|
||||||
@ -557,20 +577,20 @@ void GrTextureEffect::Impl::emitCode(EmitArgs& args) {
|
|||||||
clampCoord(useClamp[0], "x", "x", "z");
|
clampCoord(useClamp[0], "x", "x", "z");
|
||||||
clampCoord(useClamp[1], "y", "y", "w");
|
clampCoord(useClamp[1], "y", "y", "w");
|
||||||
|
|
||||||
// Additional clamping for the extra coords for kRepeatMipMap.
|
// Additional clamping for the extra coords for kRepeat with mip maps.
|
||||||
if (m[0] == ShaderMode::kRepeatMipMap) {
|
if (mipmapRepeatX) {
|
||||||
fb->codeAppendf("extraRepeatCoordX = clamp(extraRepeatCoordX, %s.x, %s.z);", clampName,
|
fb->codeAppendf("extraRepeatCoordX = clamp(extraRepeatCoordX, %s.x, %s.z);", clampName,
|
||||||
clampName);
|
clampName);
|
||||||
}
|
}
|
||||||
if (m[1] == ShaderMode::kRepeatMipMap) {
|
if (mipmapRepeatY) {
|
||||||
fb->codeAppendf("extraRepeatCoordY = clamp(extraRepeatCoordY, %s.y, %s.w);", clampName,
|
fb->codeAppendf("extraRepeatCoordY = clamp(extraRepeatCoordY, %s.y, %s.w);", clampName,
|
||||||
clampName);
|
clampName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do the 2 or 4 texture reads for kRepeatMipMap and then apply the weight(s)
|
// Do the 2 or 4 texture reads for kRepeatMipMap and then apply the weight(s)
|
||||||
// to blend between them. If neither direction is kRepeatMipMap do a single
|
// to blend between them. If neither direction is repeat or not using mip maps do a single
|
||||||
// read at clampedCoord.
|
// read at clampedCoord.
|
||||||
if (m[0] == ShaderMode::kRepeatMipMap && m[1] == ShaderMode::kRepeatMipMap) {
|
if (mipmapRepeatX && mipmapRepeatY) {
|
||||||
fb->codeAppendf(
|
fb->codeAppendf(
|
||||||
"half4 textureColor ="
|
"half4 textureColor ="
|
||||||
" mix(mix(%s, %s, repeatCoordWeightX),"
|
" mix(mix(%s, %s, repeatCoordWeightX),"
|
||||||
@ -581,11 +601,11 @@ void GrTextureEffect::Impl::emitCode(EmitArgs& args) {
|
|||||||
read("float2(clampedCoord.x, extraRepeatCoordY)").c_str(),
|
read("float2(clampedCoord.x, extraRepeatCoordY)").c_str(),
|
||||||
read("float2(extraRepeatCoordX, extraRepeatCoordY)").c_str());
|
read("float2(extraRepeatCoordX, extraRepeatCoordY)").c_str());
|
||||||
|
|
||||||
} else if (m[0] == ShaderMode::kRepeatMipMap) {
|
} else if (mipmapRepeatX) {
|
||||||
fb->codeAppendf("half4 textureColor = mix(%s, %s, repeatCoordWeightX);",
|
fb->codeAppendf("half4 textureColor = mix(%s, %s, repeatCoordWeightX);",
|
||||||
read("clampedCoord").c_str(),
|
read("clampedCoord").c_str(),
|
||||||
read("float2(extraRepeatCoordX, clampedCoord.y)").c_str());
|
read("float2(extraRepeatCoordX, clampedCoord.y)").c_str());
|
||||||
} else if (m[1] == ShaderMode::kRepeatMipMap) {
|
} else if (mipmapRepeatY) {
|
||||||
fb->codeAppendf("half4 textureColor = mix(%s, %s, repeatCoordWeightY);",
|
fb->codeAppendf("half4 textureColor = mix(%s, %s, repeatCoordWeightY);",
|
||||||
read("clampedCoord").c_str(),
|
read("clampedCoord").c_str(),
|
||||||
read("float2(clampedCoord.x, extraRepeatCoordY)").c_str());
|
read("float2(clampedCoord.x, extraRepeatCoordY)").c_str());
|
||||||
@ -599,30 +619,33 @@ void GrTextureEffect::Impl::emitCode(EmitArgs& args) {
|
|||||||
|
|
||||||
// Calculate the amount the coord moved for clamping. This will be used
|
// Calculate the amount the coord moved for clamping. This will be used
|
||||||
// to implement shader-based filtering for kClampToBorder and kRepeat.
|
// to implement shader-based filtering for kClampToBorder and kRepeat.
|
||||||
|
bool repeatLinearFilterX = m[0] == ShaderMode::kRepeat_Linear_None ||
|
||||||
if (m[0] == ShaderMode::kRepeatLinear || m[0] == ShaderMode::kClampToBorderFilter) {
|
m[0] == ShaderMode::kRepeat_Linear_Mipmap;
|
||||||
|
bool repeatLinearFilterY = m[1] == ShaderMode::kRepeat_Linear_None ||
|
||||||
|
m[1] == ShaderMode::kRepeat_Linear_Mipmap;
|
||||||
|
if (repeatLinearFilterX || m[0] == ShaderMode::kClampToBorder_Filter) {
|
||||||
fb->codeAppend("half errX = half(subsetCoord.x - clampedCoord.x);");
|
fb->codeAppend("half errX = half(subsetCoord.x - clampedCoord.x);");
|
||||||
if (m[0] == ShaderMode::kRepeatLinear) {
|
if (repeatLinearFilterX) {
|
||||||
fb->codeAppendf("float repeatCoordX = errX > 0 ? %s.x : %s.z;",
|
fb->codeAppendf("float repeatCoordX = errX > 0 ? %s.x : %s.z;",
|
||||||
clampName, clampName);
|
clampName, clampName);
|
||||||
repeatLinearReadX = read("float2(repeatCoordX, clampedCoord.y)");
|
repeatLinearReadX = read("float2(repeatCoordX, clampedCoord.y)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m[1] == ShaderMode::kRepeatLinear || m[1] == ShaderMode::kClampToBorderFilter) {
|
if (repeatLinearFilterY || m[1] == ShaderMode::kClampToBorder_Filter) {
|
||||||
fb->codeAppend("half errY = half(subsetCoord.y - clampedCoord.y);");
|
fb->codeAppend("half errY = half(subsetCoord.y - clampedCoord.y);");
|
||||||
if (m[1] == ShaderMode::kRepeatLinear) {
|
if (repeatLinearFilterY) {
|
||||||
fb->codeAppendf("float repeatCoordY = errY > 0 ? %s.y : %s.w;",
|
fb->codeAppendf("float repeatCoordY = errY > 0 ? %s.y : %s.w;",
|
||||||
clampName, clampName);
|
clampName, clampName);
|
||||||
repeatLinearReadY = read("float2(clampedCoord.x, repeatCoordY)");
|
repeatLinearReadY = read("float2(clampedCoord.x, repeatCoordY)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add logic for kRepeatLinear. Do 1 or 3 more texture reads depending
|
// Add logic for kRepeat + linear filter. Do 1 or 3 more texture reads depending
|
||||||
// on whether both modes are kRepeat and whether we're near a single subset edge
|
// on whether both modes are kRepeat and whether we're near a single subset edge
|
||||||
// or a corner. Then blend the multiple reads using the err values calculated
|
// or a corner. Then blend the multiple reads using the err values calculated
|
||||||
// above.
|
// above.
|
||||||
const char* ifStr = "if";
|
const char* ifStr = "if";
|
||||||
if (m[0] == ShaderMode::kRepeatLinear && m[1] == ShaderMode::kRepeatLinear) {
|
if (repeatLinearFilterX && repeatLinearFilterY) {
|
||||||
auto repeatLinearReadXY = read("float2(repeatCoordX, repeatCoordY)");
|
auto repeatLinearReadXY = read("float2(repeatCoordX, repeatCoordY)");
|
||||||
fb->codeAppendf(
|
fb->codeAppendf(
|
||||||
"if (errX != 0 && errY != 0) {"
|
"if (errX != 0 && errY != 0) {"
|
||||||
@ -635,14 +658,14 @@ void GrTextureEffect::Impl::emitCode(EmitArgs& args) {
|
|||||||
repeatLinearReadXY.c_str());
|
repeatLinearReadXY.c_str());
|
||||||
ifStr = "else if";
|
ifStr = "else if";
|
||||||
}
|
}
|
||||||
if (m[0] == ShaderMode::kRepeatLinear) {
|
if (repeatLinearFilterX) {
|
||||||
fb->codeAppendf(
|
fb->codeAppendf(
|
||||||
"%s (errX != 0) {"
|
"%s (errX != 0) {"
|
||||||
" textureColor = mix(textureColor, %s, abs(errX));"
|
" textureColor = mix(textureColor, %s, abs(errX));"
|
||||||
"}",
|
"}",
|
||||||
ifStr, repeatLinearReadX.c_str());
|
ifStr, repeatLinearReadX.c_str());
|
||||||
}
|
}
|
||||||
if (m[1] == ShaderMode::kRepeatLinear) {
|
if (repeatLinearFilterY) {
|
||||||
fb->codeAppendf(
|
fb->codeAppendf(
|
||||||
"%s (errY != 0) {"
|
"%s (errY != 0) {"
|
||||||
" textureColor = mix(textureColor, %s, abs(errY));"
|
" textureColor = mix(textureColor, %s, abs(errY));"
|
||||||
@ -652,17 +675,17 @@ void GrTextureEffect::Impl::emitCode(EmitArgs& args) {
|
|||||||
|
|
||||||
// Do soft edge shader filtering against border color for kClampToBorderFilter using
|
// Do soft edge shader filtering against border color for kClampToBorderFilter using
|
||||||
// the err values calculated above.
|
// the err values calculated above.
|
||||||
if (m[0] == ShaderMode::kClampToBorderFilter) {
|
if (m[0] == ShaderMode::kClampToBorder_Filter) {
|
||||||
fb->codeAppendf("textureColor = mix(textureColor, %s, min(abs(errX), 1));", borderName);
|
fb->codeAppendf("textureColor = mix(textureColor, %s, min(abs(errX), 1));", borderName);
|
||||||
}
|
}
|
||||||
if (m[1] == ShaderMode::kClampToBorderFilter) {
|
if (m[1] == ShaderMode::kClampToBorder_Filter) {
|
||||||
fb->codeAppendf("textureColor = mix(textureColor, %s, min(abs(errY), 1));", borderName);
|
fb->codeAppendf("textureColor = mix(textureColor, %s, min(abs(errY), 1));", borderName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do hard-edge shader transition to border color for kClampToBorderNearest at the
|
// Do hard-edge shader transition to border color for kClampToBorderNearest at the
|
||||||
// subset boundaries. Snap the input coordinates to nearest neighbor (with an
|
// subset boundaries. Snap the input coordinates to nearest neighbor (with an
|
||||||
// epsilon) before comparing to the subset rect to avoid GPU interpolation errors
|
// epsilon) before comparing to the subset rect to avoid GPU interpolation errors
|
||||||
if (m[0] == ShaderMode::kClampToBorderNearest) {
|
if (m[0] == ShaderMode::kClampToBorder_Nearest) {
|
||||||
fb->codeAppendf(
|
fb->codeAppendf(
|
||||||
"float snappedX = floor(inCoord.x + 0.001) + 0.5;"
|
"float snappedX = floor(inCoord.x + 0.001) + 0.5;"
|
||||||
"if (snappedX < %s.x || snappedX > %s.z) {"
|
"if (snappedX < %s.x || snappedX > %s.z) {"
|
||||||
@ -670,7 +693,7 @@ void GrTextureEffect::Impl::emitCode(EmitArgs& args) {
|
|||||||
"}",
|
"}",
|
||||||
subsetName, subsetName, borderName);
|
subsetName, subsetName, borderName);
|
||||||
}
|
}
|
||||||
if (m[1] == ShaderMode::kClampToBorderNearest) {
|
if (m[1] == ShaderMode::kClampToBorder_Nearest) {
|
||||||
fb->codeAppendf(
|
fb->codeAppendf(
|
||||||
"float snappedY = floor(inCoord.y + 0.001) + 0.5;"
|
"float snappedY = floor(inCoord.y + 0.001) + 0.5;"
|
||||||
"if (snappedY < %s.y || snappedY > %s.w) {"
|
"if (snappedY < %s.y || snappedY > %s.w) {"
|
||||||
@ -796,26 +819,15 @@ GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrTextureEffect);
|
|||||||
#if GR_TEST_UTILS
|
#if GR_TEST_UTILS
|
||||||
std::unique_ptr<GrFragmentProcessor> GrTextureEffect::TestCreate(GrProcessorTestData* testData) {
|
std::unique_ptr<GrFragmentProcessor> GrTextureEffect::TestCreate(GrProcessorTestData* testData) {
|
||||||
auto [view, ct, at] = testData->randomView();
|
auto [view, ct, at] = testData->randomView();
|
||||||
Mode wrapModes[2];
|
Wrap wrapModes[2];
|
||||||
GrTest::TestWrapModes(testData->fRandom, wrapModes);
|
GrTest::TestWrapModes(testData->fRandom, wrapModes);
|
||||||
|
|
||||||
Filter filter;
|
Filter filter = testData->fRandom->nextBool() ? Filter::kLinear : Filter::kNearest;
|
||||||
|
MipmapMode mm = MipmapMode::kNone;
|
||||||
if (view.asTextureProxy()->mipmapped() == GrMipmapped::kYes) {
|
if (view.asTextureProxy()->mipmapped() == GrMipmapped::kYes) {
|
||||||
switch (testData->fRandom->nextULessThan(3)) {
|
mm = testData->fRandom->nextBool() ? MipmapMode::kLinear : MipmapMode::kNone;
|
||||||
case 0:
|
|
||||||
filter = Filter::kNearest;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
filter = Filter::kLinear;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
filter = Filter::kMipMap;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
filter = testData->fRandom->nextBool() ? Filter::kLinear : Filter::kNearest;
|
|
||||||
}
|
}
|
||||||
GrSamplerState params(wrapModes, filter);
|
GrSamplerState params(wrapModes, filter, mm);
|
||||||
|
|
||||||
const SkMatrix& matrix = GrTest::TestMatrix(testData->fRandom);
|
const SkMatrix& matrix = GrTest::TestMatrix(testData->fRandom);
|
||||||
return GrTextureEffect::Make(std::move(view), at, matrix, params, *testData->caps());
|
return GrTextureEffect::Make(std::move(view), at, matrix, params, *testData->caps());
|
||||||
|
@ -23,7 +23,8 @@ public:
|
|||||||
GrSurfaceProxyView,
|
GrSurfaceProxyView,
|
||||||
SkAlphaType,
|
SkAlphaType,
|
||||||
const SkMatrix& = SkMatrix::I(),
|
const SkMatrix& = SkMatrix::I(),
|
||||||
GrSamplerState::Filter = GrSamplerState::Filter::kNearest);
|
GrSamplerState::Filter = GrSamplerState::Filter::kNearest,
|
||||||
|
GrSamplerState::MipmapMode mipmapMode = GrSamplerState::MipmapMode::kNone);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make from a full GrSamplerState. Caps are required to determine support for kClampToBorder.
|
* Make from a full GrSamplerState. Caps are required to determine support for kClampToBorder.
|
||||||
@ -124,16 +125,19 @@ private:
|
|||||||
* filter.
|
* filter.
|
||||||
*/
|
*/
|
||||||
enum class ShaderMode : uint16_t {
|
enum class ShaderMode : uint16_t {
|
||||||
kNone, // Using HW mode
|
kNone, // Using HW mode
|
||||||
kClamp, // Shader based clamp, no filter specialization
|
kClamp, // Shader based clamp, no filter specialization
|
||||||
kRepeatNearest, // Simple repeat for nearest sampling
|
kRepeat_Nearest_None, // Simple repeat for nearest sampling, no mipmapping
|
||||||
kRepeatLinear, // Filter across the subset boundary for kRepeat mode
|
kRepeat_Linear_None, // Filter the subset boundary for kRepeat mode, no mip mapping
|
||||||
kRepeatMipMap, // Logic for LOD selection with kRepeat mode.
|
kRepeat_Linear_Mipmap, // Logic for linear filtering and LOD selection with kRepeat mode.
|
||||||
kMirrorRepeat, // Mirror repeat (doesn't depend on filter))
|
kRepeat_Nearest_Mipmap, // Logic for nearest filtering and LOD selection with kRepeat mode.
|
||||||
kClampToBorderNearest, // Logic for hard transition to border color when not filtering.
|
kMirrorRepeat, // Mirror repeat (doesn't depend on filter))
|
||||||
kClampToBorderFilter, // Logic for fading to border color when filtering.
|
kClampToBorder_Nearest, // Logic for hard transition to border color when not filtering.
|
||||||
|
kClampToBorder_Filter, // Logic for fading to border color when filtering.
|
||||||
};
|
};
|
||||||
static ShaderMode GetShaderMode(GrSamplerState::WrapMode, GrSamplerState::Filter);
|
static ShaderMode GetShaderMode(GrSamplerState::WrapMode,
|
||||||
|
GrSamplerState::Filter,
|
||||||
|
GrSamplerState::MipmapMode);
|
||||||
static bool ShaderModeIsClampToBorder(ShaderMode);
|
static bool ShaderModeIsClampToBorder(ShaderMode);
|
||||||
|
|
||||||
GrSurfaceProxyView fView;
|
GrSurfaceProxyView fView;
|
||||||
|
@ -116,7 +116,7 @@ std::unique_ptr<GrFragmentProcessor> GrYUVtoRGBEffect::Make(GrSurfaceProxyView v
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (subset) {
|
if (subset) {
|
||||||
SkASSERT(samplerState.filter() != GrSamplerState::Filter::kMipMap);
|
SkASSERT(samplerState.mipmapped() == GrMipmapped::kNo);
|
||||||
if (makeLinearWithSnap) {
|
if (makeLinearWithSnap) {
|
||||||
// The plane is subsampled and we have an overall subset on the image. We're
|
// The plane is subsampled and we have an overall subset on the image. We're
|
||||||
// emulating do_fancy_upsampling using linear filtering but snapping look ups to the
|
// emulating do_fancy_upsampling using linear filtering but snapping look ups to the
|
||||||
@ -137,7 +137,6 @@ std::unique_ptr<GrFragmentProcessor> GrYUVtoRGBEffect::Make(GrSurfaceProxyView v
|
|||||||
*planeMatrix, samplerState, planeSubset,
|
*planeMatrix, samplerState, planeSubset,
|
||||||
planeDomain, caps, planeBorders[i]);
|
planeDomain, caps, planeBorders[i]);
|
||||||
} else {
|
} else {
|
||||||
SkASSERT(samplerState.filter() != GrSamplerState::Filter::kMipMap);
|
|
||||||
planeFPs[i] = GrTextureEffect::MakeSubset(views[i], kUnknown_SkAlphaType,
|
planeFPs[i] = GrTextureEffect::MakeSubset(views[i], kUnknown_SkAlphaType,
|
||||||
*planeMatrix, samplerState, planeSubset,
|
*planeMatrix, samplerState, planeSubset,
|
||||||
caps, planeBorders[i]);
|
caps, planeBorders[i]);
|
||||||
|
@ -178,18 +178,23 @@ static GrGLenum filter_to_gl_mag_filter(GrSamplerState::Filter filter) {
|
|||||||
switch (filter) {
|
switch (filter) {
|
||||||
case GrSamplerState::Filter::kNearest: return GR_GL_NEAREST;
|
case GrSamplerState::Filter::kNearest: return GR_GL_NEAREST;
|
||||||
case GrSamplerState::Filter::kLinear: return GR_GL_LINEAR;
|
case GrSamplerState::Filter::kLinear: return GR_GL_LINEAR;
|
||||||
case GrSamplerState::Filter::kMipMap: return GR_GL_LINEAR;
|
|
||||||
}
|
}
|
||||||
SK_ABORT("Unknown filter");
|
SkUNREACHABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GrGLenum filter_to_gl_min_filter(GrSamplerState::Filter filter) {
|
static GrGLenum filter_to_gl_min_filter(GrSamplerState::Filter filter,
|
||||||
switch (filter) {
|
GrSamplerState::MipmapMode mm) {
|
||||||
case GrSamplerState::Filter::kNearest: return GR_GL_NEAREST;
|
switch (mm) {
|
||||||
case GrSamplerState::Filter::kLinear: return GR_GL_LINEAR;
|
case GrSamplerState::MipmapMode::kNone:
|
||||||
case GrSamplerState::Filter::kMipMap: return GR_GL_LINEAR_MIPMAP_LINEAR;
|
return filter_to_gl_mag_filter(filter);
|
||||||
|
case GrSamplerState::MipmapMode::kLinear:
|
||||||
|
switch (filter) {
|
||||||
|
case GrSamplerState::Filter::kNearest: return GR_GL_NEAREST_MIPMAP_LINEAR;
|
||||||
|
case GrSamplerState::Filter::kLinear: return GR_GL_LINEAR_MIPMAP_LINEAR;
|
||||||
|
}
|
||||||
|
SkUNREACHABLE;
|
||||||
}
|
}
|
||||||
SK_ABORT("Unknown filter");
|
SkUNREACHABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline GrGLenum wrap_mode_to_gl_wrap(GrSamplerState::WrapMode wrapMode,
|
static inline GrGLenum wrap_mode_to_gl_wrap(GrSamplerState::WrapMode wrapMode,
|
||||||
@ -203,7 +208,7 @@ static inline GrGLenum wrap_mode_to_gl_wrap(GrSamplerState::WrapMode wrapMode,
|
|||||||
SkASSERT(caps.clampToBorderSupport());
|
SkASSERT(caps.clampToBorderSupport());
|
||||||
return GR_GL_CLAMP_TO_BORDER;
|
return GR_GL_CLAMP_TO_BORDER;
|
||||||
}
|
}
|
||||||
SK_ABORT("Unknown wrap mode");
|
SkUNREACHABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -240,10 +245,10 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fSamplers[index] = s;
|
fSamplers[index] = s;
|
||||||
auto minFilter = filter_to_gl_min_filter(state.filter());
|
GrGLenum minFilter = filter_to_gl_min_filter(state.filter(), state.mipmapMode());
|
||||||
auto magFilter = filter_to_gl_mag_filter(state.filter());
|
GrGLenum magFilter = filter_to_gl_mag_filter(state.filter());
|
||||||
auto wrapX = wrap_mode_to_gl_wrap(state.wrapModeX(), fGpu->glCaps());
|
GrGLenum wrapX = wrap_mode_to_gl_wrap(state.wrapModeX(), fGpu->glCaps());
|
||||||
auto wrapY = wrap_mode_to_gl_wrap(state.wrapModeY(), fGpu->glCaps());
|
GrGLenum wrapY = wrap_mode_to_gl_wrap(state.wrapModeY(), fGpu->glCaps());
|
||||||
GR_GL_CALL(fGpu->glInterface(),
|
GR_GL_CALL(fGpu->glInterface(),
|
||||||
SamplerParameteri(s, GR_GL_TEXTURE_MIN_FILTER, minFilter));
|
SamplerParameteri(s, GR_GL_TEXTURE_MIN_FILTER, minFilter));
|
||||||
GR_GL_CALL(fGpu->glInterface(),
|
GR_GL_CALL(fGpu->glInterface(),
|
||||||
@ -2574,37 +2579,32 @@ void GrGLGpu::bindTexture(int unitIdx, GrSamplerState samplerState, const GrSwiz
|
|||||||
fHWTextureUnitBindings[unitIdx].setBoundID(target, textureID);
|
fHWTextureUnitBindings[unitIdx].setBoundID(target, textureID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (samplerState.filter() == GrSamplerState::Filter::kMipMap) {
|
if (samplerState.mipmapped() == GrMipmapped::kYes) {
|
||||||
if (!this->caps()->mipmapSupport() ||
|
if (!this->caps()->mipmapSupport() ||
|
||||||
texture->texturePriv().mipmapped() == GrMipmapped::kNo) {
|
texture->texturePriv().mipmapped() == GrMipmapped::kNo) {
|
||||||
samplerState.setFilterMode(GrSamplerState::Filter::kLinear);
|
samplerState.setMipmapMode(GrSamplerState::MipmapMode::kNone);
|
||||||
|
} else {
|
||||||
|
SkASSERT(!texture->texturePriv().mipmapsAreDirty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SK_DEBUG
|
|
||||||
// We were supposed to ensure MipMaps were up-to-date before getting here.
|
|
||||||
if (samplerState.filter() == GrSamplerState::Filter::kMipMap) {
|
|
||||||
SkASSERT(!texture->texturePriv().mipmapsAreDirty());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
auto timestamp = texture->parameters()->resetTimestamp();
|
auto timestamp = texture->parameters()->resetTimestamp();
|
||||||
bool setAll = timestamp < fResetTimestampForTextureParameters;
|
bool setAll = timestamp < fResetTimestampForTextureParameters;
|
||||||
|
|
||||||
const GrGLTextureParameters::SamplerOverriddenState* samplerStateToRecord = nullptr;
|
const GrGLTextureParameters::SamplerOverriddenState* samplerStateToRecord = nullptr;
|
||||||
GrGLTextureParameters::SamplerOverriddenState newSamplerState;
|
GrGLTextureParameters::SamplerOverriddenState newSamplerState;
|
||||||
if (fSamplerObjectCache) {
|
if (fSamplerObjectCache) {
|
||||||
fSamplerObjectCache->bindSampler(unitIdx, samplerState);
|
fSamplerObjectCache->bindSampler(unitIdx, samplerState);
|
||||||
if (this->glCaps().mustSetTexParameterMinFilterToEnableMipmapping()) {
|
if (this->glCaps().mustSetTexParameterMinFilterToEnableMipmapping()) {
|
||||||
if (samplerState.filter() == GrSamplerState::Filter::kMipMap) {
|
if (samplerState.mipmapped() == GrMipmapped::kYes) {
|
||||||
|
GrGLenum minFilter = filter_to_gl_min_filter(samplerState.filter(),
|
||||||
|
samplerState.mipmapMode());
|
||||||
const GrGLTextureParameters::SamplerOverriddenState& oldSamplerState =
|
const GrGLTextureParameters::SamplerOverriddenState& oldSamplerState =
|
||||||
texture->parameters()->samplerOverriddenState();
|
texture->parameters()->samplerOverriddenState();
|
||||||
if (setAll || oldSamplerState.fMinFilter != GR_GL_LINEAR_MIPMAP_LINEAR) {
|
if (setAll || oldSamplerState.fMinFilter != minFilter) {
|
||||||
this->setTextureUnit(unitIdx);
|
this->setTextureUnit(unitIdx);
|
||||||
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MIN_FILTER,
|
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MIN_FILTER, minFilter));
|
||||||
GR_GL_LINEAR_MIPMAP_LINEAR));
|
|
||||||
newSamplerState = oldSamplerState;
|
newSamplerState = oldSamplerState;
|
||||||
newSamplerState.fMinFilter = GR_GL_LINEAR_MIPMAP_LINEAR;
|
newSamplerState.fMinFilter = minFilter;
|
||||||
samplerStateToRecord = &newSamplerState;
|
samplerStateToRecord = &newSamplerState;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2614,7 +2614,8 @@ void GrGLGpu::bindTexture(int unitIdx, GrSamplerState samplerState, const GrSwiz
|
|||||||
texture->parameters()->samplerOverriddenState();
|
texture->parameters()->samplerOverriddenState();
|
||||||
samplerStateToRecord = &newSamplerState;
|
samplerStateToRecord = &newSamplerState;
|
||||||
|
|
||||||
newSamplerState.fMinFilter = filter_to_gl_min_filter(samplerState.filter());
|
newSamplerState.fMinFilter = filter_to_gl_min_filter(samplerState.filter(),
|
||||||
|
samplerState.mipmapMode());
|
||||||
newSamplerState.fMagFilter = filter_to_gl_mag_filter(samplerState.filter());
|
newSamplerState.fMagFilter = filter_to_gl_mag_filter(samplerState.filter());
|
||||||
|
|
||||||
newSamplerState.fWrapS = wrap_mode_to_gl_wrap(samplerState.wrapModeX(), this->glCaps());
|
newSamplerState.fWrapS = wrap_mode_to_gl_wrap(samplerState.wrapModeX(), this->glCaps());
|
||||||
|
@ -41,15 +41,21 @@ static inline MTLSamplerAddressMode wrap_mode_to_mtl_sampler_address(
|
|||||||
}
|
}
|
||||||
|
|
||||||
GrMtlSampler* GrMtlSampler::Create(const GrMtlGpu* gpu, GrSamplerState samplerState) {
|
GrMtlSampler* GrMtlSampler::Create(const GrMtlGpu* gpu, GrSamplerState samplerState) {
|
||||||
static MTLSamplerMinMagFilter mtlMinMagFilterModes[] = {
|
MTLSamplerMinMagFilter minMagFilter = [&] {
|
||||||
MTLSamplerMinMagFilterNearest,
|
switch (samplerState.filter()) {
|
||||||
MTLSamplerMinMagFilterLinear,
|
case GrSamplerState::Filter::kNearest: return MTLSamplerMinMagFilterNearest;
|
||||||
MTLSamplerMinMagFilterLinear
|
case GrSamplerState::Filter::kLinear: return MTLSamplerMinMagFilterLinear;
|
||||||
};
|
}
|
||||||
|
SkUNREACHABLE;
|
||||||
|
}();
|
||||||
|
|
||||||
static_assert((int)GrSamplerState::Filter::kNearest == 0);
|
MTLSamplerMipFilter mipFilter = [&] {
|
||||||
static_assert((int)GrSamplerState::Filter::kLinear == 1);
|
switch (samplerState.mipmapMode()) {
|
||||||
static_assert((int)GrSamplerState::Filter::kMipMap == 2);
|
case GrSamplerState::MipmapMode::kNone: return MTLSamplerMipFilterNotMipmapped;
|
||||||
|
case GrSamplerState::MipmapMode::kLinear: return MTLSamplerMipFilterLinear;
|
||||||
|
}
|
||||||
|
SkUNREACHABLE;
|
||||||
|
}();
|
||||||
|
|
||||||
auto samplerDesc = [[MTLSamplerDescriptor alloc] init];
|
auto samplerDesc = [[MTLSamplerDescriptor alloc] init];
|
||||||
samplerDesc.rAddressMode = MTLSamplerAddressModeClampToEdge;
|
samplerDesc.rAddressMode = MTLSamplerAddressModeClampToEdge;
|
||||||
@ -57,12 +63,11 @@ GrMtlSampler* GrMtlSampler::Create(const GrMtlGpu* gpu, GrSamplerState samplerSt
|
|||||||
gpu->mtlCaps());
|
gpu->mtlCaps());
|
||||||
samplerDesc.tAddressMode = wrap_mode_to_mtl_sampler_address(samplerState.wrapModeY(),
|
samplerDesc.tAddressMode = wrap_mode_to_mtl_sampler_address(samplerState.wrapModeY(),
|
||||||
gpu->mtlCaps());
|
gpu->mtlCaps());
|
||||||
samplerDesc.magFilter = mtlMinMagFilterModes[static_cast<int>(samplerState.filter())];
|
samplerDesc.magFilter = minMagFilter;
|
||||||
samplerDesc.minFilter = mtlMinMagFilterModes[static_cast<int>(samplerState.filter())];
|
samplerDesc.minFilter = minMagFilter;
|
||||||
samplerDesc.mipFilter = MTLSamplerMipFilterLinear;
|
samplerDesc.mipFilter = mipFilter;
|
||||||
samplerDesc.lodMinClamp = 0.0f;
|
samplerDesc.lodMinClamp = 0.0f;
|
||||||
bool useMipMaps = GrSamplerState::Filter::kMipMap == samplerState.filter();
|
samplerDesc.lodMaxClamp = FLT_MAX; // default value according to docs.
|
||||||
samplerDesc.lodMaxClamp = !useMipMaps ? 0.0f : 10000.0f;
|
|
||||||
samplerDesc.maxAnisotropy = 1.0f;
|
samplerDesc.maxAnisotropy = 1.0f;
|
||||||
samplerDesc.normalizedCoordinates = true;
|
samplerDesc.normalizedCoordinates = true;
|
||||||
if (@available(macOS 10.11, iOS 9.0, *)) {
|
if (@available(macOS 10.11, iOS 9.0, *)) {
|
||||||
|
@ -165,8 +165,7 @@ public:
|
|||||||
const char* name() const override { return "NonAALatticeOp"; }
|
const char* name() const override { return "NonAALatticeOp"; }
|
||||||
|
|
||||||
void visitProxies(const VisitProxyFunc& func) const override {
|
void visitProxies(const VisitProxyFunc& func) const override {
|
||||||
bool mipped = (GrSamplerState::Filter::kMipMap == fFilter);
|
func(fView.proxy(), GrMipmapped::kNo);
|
||||||
func(fView.proxy(), GrMipmapped(mipped));
|
|
||||||
if (fProgramInfo) {
|
if (fProgramInfo) {
|
||||||
fProgramInfo->visitFPProxies(func);
|
fProgramInfo->visitFPProxies(func);
|
||||||
} else {
|
} else {
|
||||||
|
@ -58,11 +58,13 @@ static SkSize axis_aligned_quad_size(const GrQuad& quad) {
|
|||||||
return {dw, dh};
|
return {dw, dh};
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool filter_has_effect(const GrQuad& srcQuad, const GrQuad& dstQuad) {
|
static std::tuple<bool /* filter */,
|
||||||
|
bool /* mipmap */>
|
||||||
|
filter_and_mm_have_effect(const GrQuad& srcQuad, const GrQuad& dstQuad) {
|
||||||
// If not axis-aligned in src or dst, then always say it has an effect
|
// If not axis-aligned in src or dst, then always say it has an effect
|
||||||
if (srcQuad.quadType() != GrQuad::Type::kAxisAligned ||
|
if (srcQuad.quadType() != GrQuad::Type::kAxisAligned ||
|
||||||
dstQuad.quadType() != GrQuad::Type::kAxisAligned) {
|
dstQuad.quadType() != GrQuad::Type::kAxisAligned) {
|
||||||
return true;
|
return {true, true};
|
||||||
}
|
}
|
||||||
|
|
||||||
SkRect srcRect;
|
SkRect srcRect;
|
||||||
@ -72,24 +74,26 @@ static bool filter_has_effect(const GrQuad& srcQuad, const GrQuad& dstQuad) {
|
|||||||
// top-left corners have the same fraction (so src and dst snap to the pixel grid
|
// top-left corners have the same fraction (so src and dst snap to the pixel grid
|
||||||
// identically).
|
// identically).
|
||||||
SkASSERT(srcRect.isSorted());
|
SkASSERT(srcRect.isSorted());
|
||||||
return srcRect.width() != dstRect.width() || srcRect.height() != dstRect.height() ||
|
bool filter = srcRect.width() != dstRect.width() || srcRect.height() != dstRect.height() ||
|
||||||
SkScalarFraction(srcRect.fLeft) != SkScalarFraction(dstRect.fLeft) ||
|
SkScalarFraction(srcRect.fLeft) != SkScalarFraction(dstRect.fLeft) ||
|
||||||
SkScalarFraction(srcRect.fTop) != SkScalarFraction(dstRect.fTop);
|
SkScalarFraction(srcRect.fTop) != SkScalarFraction(dstRect.fTop);
|
||||||
} else {
|
bool mm = srcRect.width() > dstRect.width() || srcRect.height() > dstRect.height();
|
||||||
// Although the quads are axis-aligned, the local coordinate system is transformed such
|
return {filter, mm};
|
||||||
// that fractionally-aligned sample centers will not align with the device coordinate system
|
|
||||||
// So disable filtering when edges are the same length and both srcQuad and dstQuad
|
|
||||||
// 0th vertex is integer aligned.
|
|
||||||
if (SkScalarIsInt(srcQuad.x(0)) && SkScalarIsInt(srcQuad.y(0)) &&
|
|
||||||
SkScalarIsInt(dstQuad.x(0)) && SkScalarIsInt(dstQuad.y(0))) {
|
|
||||||
// Extract edge lengths
|
|
||||||
SkSize srcSize = axis_aligned_quad_size(srcQuad);
|
|
||||||
SkSize dstSize = axis_aligned_quad_size(dstQuad);
|
|
||||||
return srcSize.fWidth != dstSize.fWidth || srcSize.fHeight != dstSize.fHeight;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// Extract edge lengths
|
||||||
|
SkSize srcSize = axis_aligned_quad_size(srcQuad);
|
||||||
|
SkSize dstSize = axis_aligned_quad_size(dstQuad);
|
||||||
|
// Although the quads are axis-aligned, the local coordinate system is transformed such
|
||||||
|
// that fractionally-aligned sample centers will not align with the device coordinate system
|
||||||
|
// So disable filtering when edges are the same length and both srcQuad and dstQuad
|
||||||
|
// 0th vertex is integer aligned.
|
||||||
|
bool filter = srcSize != dstSize ||
|
||||||
|
!SkScalarIsInt(srcQuad.x(0)) ||
|
||||||
|
!SkScalarIsInt(srcQuad.y(0)) ||
|
||||||
|
!SkScalarIsInt(dstQuad.x(0)) ||
|
||||||
|
!SkScalarIsInt(dstQuad.y(0));
|
||||||
|
bool mm = srcSize.fWidth > dstSize.fWidth || srcSize.fHeight > dstSize.fHeight;
|
||||||
|
return {filter, mm};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Describes function for normalizing src coords: [x * iw, y * ih + yOffset] can represent
|
// Describes function for normalizing src coords: [x * iw, y * ih + yOffset] can represent
|
||||||
@ -222,13 +226,14 @@ public:
|
|||||||
GrSurfaceProxyView proxyView,
|
GrSurfaceProxyView proxyView,
|
||||||
sk_sp<GrColorSpaceXform> textureXform,
|
sk_sp<GrColorSpaceXform> textureXform,
|
||||||
GrSamplerState::Filter filter,
|
GrSamplerState::Filter filter,
|
||||||
|
GrSamplerState::MipmapMode mm,
|
||||||
const SkPMColor4f& color,
|
const SkPMColor4f& color,
|
||||||
GrTextureOp::Saturate saturate,
|
GrTextureOp::Saturate saturate,
|
||||||
GrAAType aaType,
|
GrAAType aaType,
|
||||||
DrawQuad* quad,
|
DrawQuad* quad,
|
||||||
const SkRect* subset) {
|
const SkRect* subset) {
|
||||||
GrOpMemoryPool* pool = context->priv().opMemoryPool();
|
GrOpMemoryPool* pool = context->priv().opMemoryPool();
|
||||||
return pool->allocate<TextureOp>(std::move(proxyView), std::move(textureXform), filter,
|
return pool->allocate<TextureOp>(std::move(proxyView), std::move(textureXform), filter, mm,
|
||||||
color, saturate, aaType, quad, subset);
|
color, saturate, aaType, quad, subset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,6 +242,7 @@ public:
|
|||||||
int cnt,
|
int cnt,
|
||||||
int proxyRunCnt,
|
int proxyRunCnt,
|
||||||
GrSamplerState::Filter filter,
|
GrSamplerState::Filter filter,
|
||||||
|
GrSamplerState::MipmapMode mm,
|
||||||
GrTextureOp::Saturate saturate,
|
GrTextureOp::Saturate saturate,
|
||||||
GrAAType aaType,
|
GrAAType aaType,
|
||||||
SkCanvas::SrcRectConstraint constraint,
|
SkCanvas::SrcRectConstraint constraint,
|
||||||
@ -249,7 +255,7 @@ public:
|
|||||||
GrOpMemoryPool* pool = context->priv().opMemoryPool();
|
GrOpMemoryPool* pool = context->priv().opMemoryPool();
|
||||||
void* mem = pool->allocate(size);
|
void* mem = pool->allocate(size);
|
||||||
return std::unique_ptr<GrDrawOp>(
|
return std::unique_ptr<GrDrawOp>(
|
||||||
new (mem) TextureOp(set, cnt, proxyRunCnt, filter, saturate, aaType, constraint,
|
new (mem) TextureOp(set, cnt, proxyRunCnt, filter, mm, saturate, aaType, constraint,
|
||||||
viewMatrix, std::move(textureColorSpaceXform)));
|
viewMatrix, std::move(textureColorSpaceXform)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,7 +268,7 @@ public:
|
|||||||
const char* name() const override { return "TextureOp"; }
|
const char* name() const override { return "TextureOp"; }
|
||||||
|
|
||||||
void visitProxies(const VisitProxyFunc& func) const override {
|
void visitProxies(const VisitProxyFunc& func) const override {
|
||||||
bool mipped = (GrSamplerState::Filter::kMipMap == fMetadata.filter());
|
bool mipped = (fMetadata.mipmapMode() != GrSamplerState::MipmapMode::kNone);
|
||||||
for (unsigned p = 0; p < fMetadata.fProxyCount; ++p) {
|
for (unsigned p = 0; p < fMetadata.fProxyCount; ++p) {
|
||||||
func(fViewCountPairs[p].fProxy.get(), GrMipmapped(mipped));
|
func(fViewCountPairs[p].fProxy.get(), GrMipmapped(mipped));
|
||||||
}
|
}
|
||||||
@ -277,9 +283,10 @@ public:
|
|||||||
str.appendf("# draws: %d\n", fQuads.count());
|
str.appendf("# draws: %d\n", fQuads.count());
|
||||||
auto iter = fQuads.iterator();
|
auto iter = fQuads.iterator();
|
||||||
for (unsigned p = 0; p < fMetadata.fProxyCount; ++p) {
|
for (unsigned p = 0; p < fMetadata.fProxyCount; ++p) {
|
||||||
str.appendf("Proxy ID: %d, Filter: %d\n",
|
str.appendf("Proxy ID: %d, Filter: %d, MM: %d\n",
|
||||||
fViewCountPairs[p].fProxy->uniqueID().asUInt(),
|
fViewCountPairs[p].fProxy->uniqueID().asUInt(),
|
||||||
static_cast<int>(fMetadata.fFilter));
|
static_cast<int>(fMetadata.fFilter),
|
||||||
|
static_cast<int>(fMetadata.fMipmapMode));
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while(i < fViewCountPairs[p].fQuadCnt && iter.next()) {
|
while(i < fViewCountPairs[p].fQuadCnt && iter.next()) {
|
||||||
const GrQuad* quad = iter.deviceQuad();
|
const GrQuad* quad = iter.deviceQuad();
|
||||||
@ -368,12 +375,16 @@ private:
|
|||||||
// performance (since texture ops are one of the most commonly used in an app).
|
// performance (since texture ops are one of the most commonly used in an app).
|
||||||
struct Metadata {
|
struct Metadata {
|
||||||
// AAType must be filled after initialization; ColorType is determined in finalize()
|
// AAType must be filled after initialization; ColorType is determined in finalize()
|
||||||
Metadata(const GrSwizzle& swizzle, GrSamplerState::Filter filter,
|
Metadata(const GrSwizzle& swizzle,
|
||||||
GrQuadPerEdgeAA::Subset subset, GrTextureOp::Saturate saturate)
|
GrSamplerState::Filter filter,
|
||||||
|
GrSamplerState::MipmapMode mm,
|
||||||
|
GrQuadPerEdgeAA::Subset subset,
|
||||||
|
GrTextureOp::Saturate saturate)
|
||||||
: fSwizzle(swizzle)
|
: fSwizzle(swizzle)
|
||||||
, fProxyCount(1)
|
, fProxyCount(1)
|
||||||
, fTotalQuadCount(1)
|
, fTotalQuadCount(1)
|
||||||
, fFilter(static_cast<uint16_t>(filter))
|
, fFilter(static_cast<uint16_t>(filter))
|
||||||
|
, fMipmapMode(static_cast<uint16_t>(mm))
|
||||||
, fAAType(static_cast<uint16_t>(GrAAType::kNone))
|
, fAAType(static_cast<uint16_t>(GrAAType::kNone))
|
||||||
, fColorType(static_cast<uint16_t>(ColorType::kNone))
|
, fColorType(static_cast<uint16_t>(ColorType::kNone))
|
||||||
, fSubset(static_cast<uint16_t>(subset))
|
, fSubset(static_cast<uint16_t>(subset))
|
||||||
@ -386,15 +397,19 @@ private:
|
|||||||
|
|
||||||
// These must be based on uint16_t to help MSVC's pack bitfields optimally
|
// These must be based on uint16_t to help MSVC's pack bitfields optimally
|
||||||
uint16_t fFilter : 2; // GrSamplerState::Filter
|
uint16_t fFilter : 2; // GrSamplerState::Filter
|
||||||
|
uint16_t fMipmapMode : 2; // GrSamplerState::MipmapMode
|
||||||
uint16_t fAAType : 2; // GrAAType
|
uint16_t fAAType : 2; // GrAAType
|
||||||
uint16_t fColorType : 2; // GrQuadPerEdgeAA::ColorType
|
uint16_t fColorType : 2; // GrQuadPerEdgeAA::ColorType
|
||||||
uint16_t fSubset : 1; // bool
|
uint16_t fSubset : 1; // bool
|
||||||
uint16_t fSaturate : 1; // bool
|
uint16_t fSaturate : 1; // bool
|
||||||
uint16_t fUnused : 8; // # of bits left before Metadata exceeds 8 bytes
|
uint16_t fUnused : 6; // # of bits left before Metadata exceeds 8 bytes
|
||||||
|
|
||||||
GrSamplerState::Filter filter() const {
|
GrSamplerState::Filter filter() const {
|
||||||
return static_cast<GrSamplerState::Filter>(fFilter);
|
return static_cast<GrSamplerState::Filter>(fFilter);
|
||||||
}
|
}
|
||||||
|
GrSamplerState::MipmapMode mipmapMode() const {
|
||||||
|
return static_cast<GrSamplerState::MipmapMode>(fMipmapMode);
|
||||||
|
}
|
||||||
GrAAType aaType() const { return static_cast<GrAAType>(fAAType); }
|
GrAAType aaType() const { return static_cast<GrAAType>(fAAType); }
|
||||||
ColorType colorType() const { return static_cast<ColorType>(fColorType); }
|
ColorType colorType() const { return static_cast<ColorType>(fColorType); }
|
||||||
Subset subset() const { return static_cast<Subset>(fSubset); }
|
Subset subset() const { return static_cast<Subset>(fSubset); }
|
||||||
@ -449,6 +464,7 @@ private:
|
|||||||
TextureOp(GrSurfaceProxyView proxyView,
|
TextureOp(GrSurfaceProxyView proxyView,
|
||||||
sk_sp<GrColorSpaceXform> textureColorSpaceXform,
|
sk_sp<GrColorSpaceXform> textureColorSpaceXform,
|
||||||
GrSamplerState::Filter filter,
|
GrSamplerState::Filter filter,
|
||||||
|
GrSamplerState::MipmapMode mm,
|
||||||
const SkPMColor4f& color,
|
const SkPMColor4f& color,
|
||||||
GrTextureOp::Saturate saturate,
|
GrTextureOp::Saturate saturate,
|
||||||
GrAAType aaType,
|
GrAAType aaType,
|
||||||
@ -458,8 +474,7 @@ private:
|
|||||||
, fQuads(1, true /* includes locals */)
|
, fQuads(1, true /* includes locals */)
|
||||||
, fTextureColorSpaceXform(std::move(textureColorSpaceXform))
|
, fTextureColorSpaceXform(std::move(textureColorSpaceXform))
|
||||||
, fDesc(nullptr)
|
, fDesc(nullptr)
|
||||||
, fMetadata(proxyView.swizzle(), filter, Subset(!!subsetRect), saturate) {
|
, fMetadata(proxyView.swizzle(), filter, mm, Subset(!!subsetRect), saturate) {
|
||||||
|
|
||||||
// Clean up disparities between the overall aa type and edge configuration and apply
|
// Clean up disparities between the overall aa type and edge configuration and apply
|
||||||
// optimizations based on the rect and matrix when appropriate
|
// optimizations based on the rect and matrix when appropriate
|
||||||
GrQuadUtils::ResolveAAType(aaType, quad->fEdgeFlags, quad->fDevice,
|
GrQuadUtils::ResolveAAType(aaType, quad->fEdgeFlags, quad->fDevice,
|
||||||
@ -498,6 +513,7 @@ private:
|
|||||||
int cnt,
|
int cnt,
|
||||||
int proxyRunCnt,
|
int proxyRunCnt,
|
||||||
GrSamplerState::Filter filter,
|
GrSamplerState::Filter filter,
|
||||||
|
GrSamplerState::MipmapMode mm,
|
||||||
GrTextureOp::Saturate saturate,
|
GrTextureOp::Saturate saturate,
|
||||||
GrAAType aaType,
|
GrAAType aaType,
|
||||||
SkCanvas::SrcRectConstraint constraint,
|
SkCanvas::SrcRectConstraint constraint,
|
||||||
@ -507,8 +523,11 @@ private:
|
|||||||
, fQuads(cnt, true /* includes locals */)
|
, fQuads(cnt, true /* includes locals */)
|
||||||
, fTextureColorSpaceXform(std::move(textureColorSpaceXform))
|
, fTextureColorSpaceXform(std::move(textureColorSpaceXform))
|
||||||
, fDesc(nullptr)
|
, fDesc(nullptr)
|
||||||
, fMetadata(set[0].fProxyView.swizzle(), GrSamplerState::Filter::kNearest,
|
, fMetadata(set[0].fProxyView.swizzle(),
|
||||||
Subset::kNo, saturate) {
|
GrSamplerState::Filter::kNearest,
|
||||||
|
GrSamplerState::MipmapMode::kNone,
|
||||||
|
Subset::kNo,
|
||||||
|
saturate) {
|
||||||
// Update counts to reflect the batch op
|
// Update counts to reflect the batch op
|
||||||
fMetadata.fProxyCount = SkToUInt(proxyRunCnt);
|
fMetadata.fProxyCount = SkToUInt(proxyRunCnt);
|
||||||
fMetadata.fTotalQuadCount = SkToUInt(cnt);
|
fMetadata.fTotalQuadCount = SkToUInt(cnt);
|
||||||
@ -518,6 +537,7 @@ private:
|
|||||||
GrAAType netAAType = GrAAType::kNone; // aa type maximally compatible with all dst rects
|
GrAAType netAAType = GrAAType::kNone; // aa type maximally compatible with all dst rects
|
||||||
Subset netSubset = Subset::kNo;
|
Subset netSubset = Subset::kNo;
|
||||||
GrSamplerState::Filter netFilter = GrSamplerState::Filter::kNearest;
|
GrSamplerState::Filter netFilter = GrSamplerState::Filter::kNearest;
|
||||||
|
GrSamplerState::MipmapMode netMM = GrSamplerState::MipmapMode::kNone;
|
||||||
|
|
||||||
const GrSurfaceProxy* curProxy = nullptr;
|
const GrSurfaceProxy* curProxy = nullptr;
|
||||||
|
|
||||||
@ -525,6 +545,9 @@ private:
|
|||||||
// increases when set[q]'s proxy changes.
|
// increases when set[q]'s proxy changes.
|
||||||
int p = 0;
|
int p = 0;
|
||||||
for (int q = 0; q < cnt; ++q) {
|
for (int q = 0; q < cnt; ++q) {
|
||||||
|
SkASSERT(mm == GrSamplerState::MipmapMode::kNone ||
|
||||||
|
(set[0].fProxyView.proxy()->asTextureProxy()->mipmapped() ==
|
||||||
|
GrMipmapped::kYes));
|
||||||
if (q == 0) {
|
if (q == 0) {
|
||||||
// We do not placement new the first ViewCountPair since that one is allocated and
|
// We do not placement new the first ViewCountPair since that one is allocated and
|
||||||
// initialized as part of the GrTextureOp creation.
|
// initialized as part of the GrTextureOp creation.
|
||||||
@ -561,13 +584,19 @@ private:
|
|||||||
quad.fLocal = GrQuad(set[q].fSrcRect);
|
quad.fLocal = GrQuad(set[q].fSrcRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (netFilter != filter && filter_has_effect(quad.fLocal, quad.fDevice)) {
|
if (netFilter != filter || netMM != mm) {
|
||||||
// The only way netFilter != filter is if linear filtering is requested and we
|
// The only way netFilter != filter is if linear is requested and we haven't yet
|
||||||
// haven't yet found a quad that requires linear filtering (so net is still
|
// found a quad that requires linear (so net is still nearest). Similar for mip
|
||||||
// nearest).
|
// mapping.
|
||||||
SkASSERT(netFilter == GrSamplerState::Filter::kNearest &&
|
SkASSERT(netFilter <= filter);
|
||||||
filter == GrSamplerState::Filter::kLinear);
|
SkASSERT(netMM <= mm);
|
||||||
netFilter = GrSamplerState::Filter::kLinear;
|
auto [mustFilter, mustMM] = filter_and_mm_have_effect(quad.fLocal, quad.fDevice);
|
||||||
|
if (mustFilter && filter != GrSamplerState::Filter::kNearest) {
|
||||||
|
netFilter = GrSamplerState::Filter::kLinear;
|
||||||
|
}
|
||||||
|
if (mustMM && mm != GrSamplerState::MipmapMode::kNone) {
|
||||||
|
netMM = GrSamplerState::MipmapMode::kLinear;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update overall bounds of the op as the union of all quads
|
// Update overall bounds of the op as the union of all quads
|
||||||
@ -970,6 +999,9 @@ private:
|
|||||||
if (fMetadata.filter() != that->fMetadata.filter()) {
|
if (fMetadata.filter() != that->fMetadata.filter()) {
|
||||||
return CombineResult::kCannotCombine;
|
return CombineResult::kCannotCombine;
|
||||||
}
|
}
|
||||||
|
if (fMetadata.mipmapMode() != that->fMetadata.mipmapMode()) {
|
||||||
|
return CombineResult::kCannotCombine;
|
||||||
|
}
|
||||||
if (fMetadata.fSwizzle != that->fMetadata.fSwizzle) {
|
if (fMetadata.fSwizzle != that->fMetadata.fSwizzle) {
|
||||||
return CombineResult::kCannotCombine;
|
return CombineResult::kCannotCombine;
|
||||||
}
|
}
|
||||||
@ -1028,6 +1060,7 @@ std::unique_ptr<GrDrawOp> GrTextureOp::Make(GrRecordingContext* context,
|
|||||||
SkAlphaType alphaType,
|
SkAlphaType alphaType,
|
||||||
sk_sp<GrColorSpaceXform> textureXform,
|
sk_sp<GrColorSpaceXform> textureXform,
|
||||||
GrSamplerState::Filter filter,
|
GrSamplerState::Filter filter,
|
||||||
|
GrSamplerState::MipmapMode mm,
|
||||||
const SkPMColor4f& color,
|
const SkPMColor4f& color,
|
||||||
Saturate saturate,
|
Saturate saturate,
|
||||||
SkBlendMode blendMode,
|
SkBlendMode blendMode,
|
||||||
@ -1040,13 +1073,18 @@ std::unique_ptr<GrDrawOp> GrTextureOp::Make(GrRecordingContext* context,
|
|||||||
subset = nullptr;
|
subset = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter != GrSamplerState::Filter::kNearest &&
|
if (filter != GrSamplerState::Filter::kNearest || mm != GrSamplerState::MipmapMode::kNone) {
|
||||||
!filter_has_effect(quad->fLocal, quad->fDevice)) {
|
auto [mustFilter, mustMM] = filter_and_mm_have_effect(quad->fLocal, quad->fDevice);
|
||||||
filter = GrSamplerState::Filter::kNearest;
|
if (!mustFilter) {
|
||||||
|
filter = GrSamplerState::Filter::kNearest;
|
||||||
|
}
|
||||||
|
if (!mustMM) {
|
||||||
|
mm = GrSamplerState::MipmapMode::kNone;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blendMode == SkBlendMode::kSrcOver) {
|
if (blendMode == SkBlendMode::kSrcOver) {
|
||||||
return TextureOp::Make(context, std::move(proxyView), std::move(textureXform), filter,
|
return TextureOp::Make(context, std::move(proxyView), std::move(textureXform), filter, mm,
|
||||||
color, saturate, aaType, std::move(quad), subset);
|
color, saturate, aaType, std::move(quad), subset);
|
||||||
} else {
|
} else {
|
||||||
// Emulate complex blending using GrFillRectOp
|
// Emulate complex blending using GrFillRectOp
|
||||||
@ -1086,6 +1124,7 @@ public:
|
|||||||
GrRecordingContext* context,
|
GrRecordingContext* context,
|
||||||
int numEntries,
|
int numEntries,
|
||||||
GrSamplerState::Filter filter,
|
GrSamplerState::Filter filter,
|
||||||
|
GrSamplerState::MipmapMode mm,
|
||||||
GrTextureOp::Saturate saturate,
|
GrTextureOp::Saturate saturate,
|
||||||
SkCanvas::SrcRectConstraint constraint,
|
SkCanvas::SrcRectConstraint constraint,
|
||||||
const SkMatrix& viewMatrix,
|
const SkMatrix& viewMatrix,
|
||||||
@ -1094,20 +1133,27 @@ public:
|
|||||||
, fClip(clip)
|
, fClip(clip)
|
||||||
, fContext(context)
|
, fContext(context)
|
||||||
, fFilter(filter)
|
, fFilter(filter)
|
||||||
|
, fMipmapMode(mm)
|
||||||
, fSaturate(saturate)
|
, fSaturate(saturate)
|
||||||
, fConstraint(constraint)
|
, fConstraint(constraint)
|
||||||
, fViewMatrix(viewMatrix)
|
, fViewMatrix(viewMatrix)
|
||||||
, fTextureColorSpaceXform(textureColorSpaceXform)
|
, fTextureColorSpaceXform(textureColorSpaceXform)
|
||||||
, fNumLeft(numEntries) {
|
, fNumLeft(numEntries) {}
|
||||||
}
|
|
||||||
|
|
||||||
void createOp(GrRenderTargetContext::TextureSetEntry set[],
|
void createOp(GrRenderTargetContext::TextureSetEntry set[],
|
||||||
int clumpSize,
|
int clumpSize,
|
||||||
GrAAType aaType) {
|
GrAAType aaType) {
|
||||||
int clumpProxyCount = proxy_run_count(&set[fNumClumped], clumpSize);
|
int clumpProxyCount = proxy_run_count(&set[fNumClumped], clumpSize);
|
||||||
std::unique_ptr<GrDrawOp> op = TextureOp::Make(fContext, &set[fNumClumped], clumpSize,
|
std::unique_ptr<GrDrawOp> op = TextureOp::Make(fContext,
|
||||||
clumpProxyCount, fFilter, fSaturate, aaType,
|
&set[fNumClumped],
|
||||||
fConstraint, fViewMatrix,
|
clumpSize,
|
||||||
|
clumpProxyCount,
|
||||||
|
fFilter,
|
||||||
|
fMipmapMode,
|
||||||
|
fSaturate,
|
||||||
|
aaType,
|
||||||
|
fConstraint,
|
||||||
|
fViewMatrix,
|
||||||
fTextureColorSpaceXform);
|
fTextureColorSpaceXform);
|
||||||
fRTC->addDrawOp(fClip, std::move(op));
|
fRTC->addDrawOp(fClip, std::move(op));
|
||||||
|
|
||||||
@ -1123,6 +1169,7 @@ private:
|
|||||||
const GrClip* fClip;
|
const GrClip* fClip;
|
||||||
GrRecordingContext* fContext;
|
GrRecordingContext* fContext;
|
||||||
GrSamplerState::Filter fFilter;
|
GrSamplerState::Filter fFilter;
|
||||||
|
GrSamplerState::MipmapMode fMipmapMode;
|
||||||
GrTextureOp::Saturate fSaturate;
|
GrTextureOp::Saturate fSaturate;
|
||||||
SkCanvas::SrcRectConstraint fConstraint;
|
SkCanvas::SrcRectConstraint fConstraint;
|
||||||
const SkMatrix& fViewMatrix;
|
const SkMatrix& fViewMatrix;
|
||||||
@ -1140,6 +1187,7 @@ void GrTextureOp::AddTextureSetOps(GrRenderTargetContext* rtc,
|
|||||||
int cnt,
|
int cnt,
|
||||||
int proxyRunCnt,
|
int proxyRunCnt,
|
||||||
GrSamplerState::Filter filter,
|
GrSamplerState::Filter filter,
|
||||||
|
GrSamplerState::MipmapMode mm,
|
||||||
Saturate saturate,
|
Saturate saturate,
|
||||||
SkBlendMode blendMode,
|
SkBlendMode blendMode,
|
||||||
GrAAType aaType,
|
GrAAType aaType,
|
||||||
@ -1181,8 +1229,7 @@ void GrTextureOp::AddTextureSetOps(GrRenderTargetContext* rtc,
|
|||||||
? &set[i].fSrcRect : nullptr;
|
? &set[i].fSrcRect : nullptr;
|
||||||
|
|
||||||
auto op = Make(context, set[i].fProxyView, set[i].fSrcAlphaType, textureColorSpaceXform,
|
auto op = Make(context, set[i].fProxyView, set[i].fSrcAlphaType, textureColorSpaceXform,
|
||||||
filter, set[i].fColor, saturate, blendMode, aaType,
|
filter, mm, set[i].fColor, saturate, blendMode, aaType, &quad, subset);
|
||||||
&quad, subset);
|
|
||||||
rtc->addDrawOp(clip, std::move(op));
|
rtc->addDrawOp(clip, std::move(op));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -1192,13 +1239,13 @@ void GrTextureOp::AddTextureSetOps(GrRenderTargetContext* rtc,
|
|||||||
// needed to clump things together.
|
// needed to clump things together.
|
||||||
if (cnt <= std::min(GrResourceProvider::MaxNumNonAAQuads(),
|
if (cnt <= std::min(GrResourceProvider::MaxNumNonAAQuads(),
|
||||||
GrResourceProvider::MaxNumAAQuads())) {
|
GrResourceProvider::MaxNumAAQuads())) {
|
||||||
auto op = TextureOp::Make(context, set, cnt, proxyRunCnt, filter, saturate, aaType,
|
auto op = TextureOp::Make(context, set, cnt, proxyRunCnt, filter, mm, saturate, aaType,
|
||||||
constraint, viewMatrix, std::move(textureColorSpaceXform));
|
constraint, viewMatrix, std::move(textureColorSpaceXform));
|
||||||
rtc->addDrawOp(clip, std::move(op));
|
rtc->addDrawOp(clip, std::move(op));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BatchSizeLimiter state(rtc, clip, context, cnt, filter, saturate, constraint, viewMatrix,
|
BatchSizeLimiter state(rtc, clip, context, cnt, filter, mm, saturate, constraint, viewMatrix,
|
||||||
std::move(textureColorSpaceXform));
|
std::move(textureColorSpaceXform));
|
||||||
|
|
||||||
// kNone and kMSAA never get altered
|
// kNone and kMSAA never get altered
|
||||||
@ -1292,11 +1339,13 @@ GR_DRAW_OP_TEST_DEFINE(TextureOp) {
|
|||||||
SkMatrix viewMatrix = GrTest::TestMatrixPreservesRightAngles(random);
|
SkMatrix viewMatrix = GrTest::TestMatrixPreservesRightAngles(random);
|
||||||
SkPMColor4f color = SkPMColor4f::FromBytes_RGBA(SkColorToPremulGrColor(random->nextU()));
|
SkPMColor4f color = SkPMColor4f::FromBytes_RGBA(SkColorToPremulGrColor(random->nextU()));
|
||||||
GrSamplerState::Filter filter = (GrSamplerState::Filter)random->nextULessThan(
|
GrSamplerState::Filter filter = (GrSamplerState::Filter)random->nextULessThan(
|
||||||
static_cast<uint32_t>(GrSamplerState::Filter::kMipMap) + 1);
|
static_cast<uint32_t>(GrSamplerState::Filter::kLast) + 1);
|
||||||
while (mipMapped == GrMipmapped::kNo && filter == GrSamplerState::Filter::kMipMap) {
|
GrSamplerState::MipmapMode mm = GrSamplerState::MipmapMode::kNone;
|
||||||
filter = (GrSamplerState::Filter)random->nextULessThan(
|
if (mipMapped == GrMipmapped::kYes) {
|
||||||
static_cast<uint32_t>(GrSamplerState::Filter::kMipMap) + 1);
|
mm = (GrSamplerState::MipmapMode)random->nextULessThan(
|
||||||
|
static_cast<uint32_t>(GrSamplerState::MipmapMode::kLast) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto texXform = GrTest::TestColorXform(random);
|
auto texXform = GrTest::TestColorXform(random);
|
||||||
GrAAType aaType = GrAAType::kNone;
|
GrAAType aaType = GrAAType::kNone;
|
||||||
if (random->nextBool()) {
|
if (random->nextBool()) {
|
||||||
@ -1317,8 +1366,8 @@ GR_DRAW_OP_TEST_DEFINE(TextureOp) {
|
|||||||
|
|
||||||
DrawQuad quad = {GrQuad::MakeFromRect(rect, viewMatrix), GrQuad(srcRect), aaFlags};
|
DrawQuad quad = {GrQuad::MakeFromRect(rect, viewMatrix), GrQuad(srcRect), aaFlags};
|
||||||
return GrTextureOp::Make(context, std::move(proxyView), alphaType, std::move(texXform), filter,
|
return GrTextureOp::Make(context, std::move(proxyView), alphaType, std::move(texXform), filter,
|
||||||
color, saturate, SkBlendMode::kSrcOver, aaType,
|
mm, color, saturate, SkBlendMode::kSrcOver, aaType, &quad,
|
||||||
&quad, useSubset ? &srcRect : nullptr);
|
useSubset ? &srcRect : nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -45,6 +45,7 @@ public:
|
|||||||
SkAlphaType srcAlphaType,
|
SkAlphaType srcAlphaType,
|
||||||
sk_sp<GrColorSpaceXform>,
|
sk_sp<GrColorSpaceXform>,
|
||||||
GrSamplerState::Filter,
|
GrSamplerState::Filter,
|
||||||
|
GrSamplerState::MipmapMode,
|
||||||
const SkPMColor4f&,
|
const SkPMColor4f&,
|
||||||
Saturate,
|
Saturate,
|
||||||
SkBlendMode,
|
SkBlendMode,
|
||||||
@ -62,6 +63,7 @@ public:
|
|||||||
int cnt,
|
int cnt,
|
||||||
int proxyRunCnt,
|
int proxyRunCnt,
|
||||||
GrSamplerState::Filter,
|
GrSamplerState::Filter,
|
||||||
|
GrSamplerState::MipmapMode,
|
||||||
Saturate,
|
Saturate,
|
||||||
SkBlendMode,
|
SkBlendMode,
|
||||||
GrAAType,
|
GrAAType,
|
||||||
|
@ -10,8 +10,7 @@
|
|||||||
#include "src/gpu/vk/GrVkGpu.h"
|
#include "src/gpu/vk/GrVkGpu.h"
|
||||||
#include "src/gpu/vk/GrVkSamplerYcbcrConversion.h"
|
#include "src/gpu/vk/GrVkSamplerYcbcrConversion.h"
|
||||||
|
|
||||||
static inline VkSamplerAddressMode wrap_mode_to_vk_sampler_address(
|
static VkSamplerAddressMode wrap_mode_to_vk_sampler_address(GrSamplerState::WrapMode wrapMode) {
|
||||||
GrSamplerState::WrapMode wrapMode) {
|
|
||||||
switch (wrapMode) {
|
switch (wrapMode) {
|
||||||
case GrSamplerState::WrapMode::kClamp:
|
case GrSamplerState::WrapMode::kClamp:
|
||||||
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||||
@ -22,7 +21,16 @@ static inline VkSamplerAddressMode wrap_mode_to_vk_sampler_address(
|
|||||||
case GrSamplerState::WrapMode::kClampToBorder:
|
case GrSamplerState::WrapMode::kClampToBorder:
|
||||||
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||||
}
|
}
|
||||||
SK_ABORT("Unknown wrap mode.");
|
SkUNREACHABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VkSamplerMipmapMode mipmap_mode_to_vk_sampler_mipmap_mode(GrSamplerState::MipmapMode mm) {
|
||||||
|
switch (mm) {
|
||||||
|
// There is no disable mode. We use max level to disable mip mapping.
|
||||||
|
case GrSamplerState::MipmapMode::kNone: return VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||||
|
case GrSamplerState::MipmapMode::kLinear: return VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||||
|
}
|
||||||
|
SkUNREACHABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GrVkSampler* GrVkSampler::Create(GrVkGpu* gpu, GrSamplerState samplerState,
|
GrVkSampler* GrVkSampler::Create(GrVkGpu* gpu, GrSamplerState samplerState,
|
||||||
@ -45,7 +53,7 @@ GrVkSampler* GrVkSampler::Create(GrVkGpu* gpu, GrSamplerState samplerState,
|
|||||||
createInfo.flags = 0;
|
createInfo.flags = 0;
|
||||||
createInfo.magFilter = vkMagFilterModes[static_cast<int>(samplerState.filter())];
|
createInfo.magFilter = vkMagFilterModes[static_cast<int>(samplerState.filter())];
|
||||||
createInfo.minFilter = vkMinFilterModes[static_cast<int>(samplerState.filter())];
|
createInfo.minFilter = vkMinFilterModes[static_cast<int>(samplerState.filter())];
|
||||||
createInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
createInfo.mipmapMode = mipmap_mode_to_vk_sampler_mipmap_mode(samplerState.mipmapMode());
|
||||||
createInfo.addressModeU = wrap_mode_to_vk_sampler_address(samplerState.wrapModeX());
|
createInfo.addressModeU = wrap_mode_to_vk_sampler_address(samplerState.wrapModeX());
|
||||||
createInfo.addressModeV = wrap_mode_to_vk_sampler_address(samplerState.wrapModeY());
|
createInfo.addressModeV = wrap_mode_to_vk_sampler_address(samplerState.wrapModeY());
|
||||||
createInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; // Shouldn't matter
|
createInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; // Shouldn't matter
|
||||||
@ -60,7 +68,7 @@ GrVkSampler* GrVkSampler::Create(GrVkGpu* gpu, GrSamplerState samplerState,
|
|||||||
// level mip). If the filters weren't the same we could set min = 0 and max = 0.25 to force
|
// level mip). If the filters weren't the same we could set min = 0 and max = 0.25 to force
|
||||||
// the minFilter on mip level 0.
|
// the minFilter on mip level 0.
|
||||||
createInfo.minLod = 0.0f;
|
createInfo.minLod = 0.0f;
|
||||||
bool useMipMaps = GrSamplerState::Filter::kMipMap == samplerState.filter();
|
bool useMipMaps = samplerState.mipmapped() == GrMipmapped::kYes;
|
||||||
createInfo.maxLod = !useMipMaps ? 0.0f : 10000.0f;
|
createInfo.maxLod = !useMipMaps ? 0.0f : 10000.0f;
|
||||||
createInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
|
createInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
|
||||||
createInfo.unnormalizedCoordinates = VK_FALSE;
|
createInfo.unnormalizedCoordinates = VK_FALSE;
|
||||||
|
@ -302,16 +302,17 @@ std::unique_ptr<GrFragmentProcessor> SkImageShader::asFragmentProcessor(
|
|||||||
// below we check the matrix scale factors to determine how to interpret the filter
|
// below we check the matrix scale factors to determine how to interpret the filter
|
||||||
// quality setting. This completely ignores the complexity of the drawVertices case
|
// quality setting. This completely ignores the complexity of the drawVertices case
|
||||||
// where explicit local coords are provided by the caller.
|
// where explicit local coords are provided by the caller.
|
||||||
bool doBicubic;
|
bool sharpen = args.fContext->priv().options().fSharpenMipmappedTextures;
|
||||||
GrSamplerState::Filter fm = GrSkFilterQualityToGrFilterMode(
|
auto [fm, mm, bicubic] = GrInterpretFilterQuality(fImage->dimensions(),
|
||||||
fImage->width(), fImage->height(), this->resolveFiltering(args.fFilterQuality),
|
this->resolveFiltering(args.fFilterQuality),
|
||||||
args.fMatrixProvider.localToDevice(), *lm,
|
args.fMatrixProvider.localToDevice(),
|
||||||
args.fContext->priv().options().fSharpenMipmappedTextures, &doBicubic);
|
*lm,
|
||||||
|
sharpen);
|
||||||
std::unique_ptr<GrFragmentProcessor> fp;
|
std::unique_ptr<GrFragmentProcessor> fp;
|
||||||
if (doBicubic) {
|
if (bicubic) {
|
||||||
fp = producer->createBicubicFragmentProcessor(lmInverse, nullptr, nullptr, wmX, wmY);
|
fp = producer->createBicubicFragmentProcessor(lmInverse, nullptr, nullptr, wmX, wmY);
|
||||||
} else {
|
} else {
|
||||||
fp = producer->createFragmentProcessor(lmInverse, nullptr, nullptr, {wmX, wmY, fm});
|
fp = producer->createFragmentProcessor(lmInverse, nullptr, nullptr, {wmX, wmY, fm, mm});
|
||||||
}
|
}
|
||||||
if (fp) {
|
if (fp) {
|
||||||
fp = GrXfermodeFragmentProcessor::Make(std::move(fp), nullptr, SkBlendMode::kModulate);
|
fp = GrXfermodeFragmentProcessor::Make(std::move(fp), nullptr, SkBlendMode::kModulate);
|
||||||
|
@ -110,14 +110,20 @@ static void bulk_texture_rect_create_test(skiatest::Reporter* reporter, GrDirect
|
|||||||
set[i].fAAFlags = perQuadAA(i);
|
set[i].fAAFlags = perQuadAA(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
GrTextureOp::AddTextureSetOps(rtc.get(), nullptr, dContext, set, requestedTotNumQuads,
|
GrTextureOp::AddTextureSetOps(rtc.get(),
|
||||||
requestedTotNumQuads, // We alternate so proxyCnt == cnt
|
nullptr,
|
||||||
|
dContext,
|
||||||
|
set,
|
||||||
|
requestedTotNumQuads,
|
||||||
|
requestedTotNumQuads, // We alternate so proxyCnt == cnt
|
||||||
GrSamplerState::Filter::kNearest,
|
GrSamplerState::Filter::kNearest,
|
||||||
|
GrSamplerState::MipmapMode::kNone,
|
||||||
GrTextureOp::Saturate::kYes,
|
GrTextureOp::Saturate::kYes,
|
||||||
blendMode,
|
blendMode,
|
||||||
overallAA,
|
overallAA,
|
||||||
SkCanvas::kStrict_SrcRectConstraint,
|
SkCanvas::kStrict_SrcRectConstraint,
|
||||||
SkMatrix::I(), nullptr);
|
SkMatrix::I(),
|
||||||
|
nullptr);
|
||||||
|
|
||||||
GrOpsTask* opsTask = rtc->testingOnly_PeekLastOpsTask();
|
GrOpsTask* opsTask = rtc->testingOnly_PeekLastOpsTask();
|
||||||
int actualNumOps = opsTask->numOpChains();
|
int actualNumOps = opsTask->numOpChains();
|
||||||
|
@ -349,19 +349,42 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(Gr1x1TextureMipMappedTest, reporter, ctxInfo)
|
|||||||
|
|
||||||
// Create a new render target and draw 'mipmapView' into it using the provided 'filter'.
|
// Create a new render target and draw 'mipmapView' into it using the provided 'filter'.
|
||||||
static std::unique_ptr<GrRenderTargetContext> draw_mipmap_into_new_render_target(
|
static std::unique_ptr<GrRenderTargetContext> draw_mipmap_into_new_render_target(
|
||||||
GrRecordingContext* context, GrProxyProvider* proxyProvider, GrColorType colorType,
|
GrRecordingContext* context,
|
||||||
SkAlphaType alphaType, GrSurfaceProxyView mipmapView, GrSamplerState::Filter filter) {
|
GrProxyProvider* proxyProvider,
|
||||||
sk_sp<GrSurfaceProxy> renderTarget = proxyProvider->createProxy(
|
GrColorType colorType,
|
||||||
mipmapView.proxy()->backendFormat(), {1, 1}, GrRenderable::kYes, 1, GrMipmapped::kNo,
|
SkAlphaType alphaType,
|
||||||
SkBackingFit::kApprox, SkBudgeted::kYes, GrProtected::kNo);
|
GrSurfaceProxyView mipmapView,
|
||||||
|
GrSamplerState::MipmapMode mm) {
|
||||||
|
sk_sp<GrSurfaceProxy> renderTarget =
|
||||||
|
proxyProvider->createProxy(mipmapView.proxy()->backendFormat(),
|
||||||
|
{1, 1},
|
||||||
|
GrRenderable::kYes,
|
||||||
|
1,
|
||||||
|
GrMipmapped::kNo,
|
||||||
|
SkBackingFit::kApprox,
|
||||||
|
SkBudgeted::kYes,
|
||||||
|
GrProtected::kNo);
|
||||||
|
|
||||||
auto rtc = GrRenderTargetContext::Make(
|
auto rtc = GrRenderTargetContext::Make(context,
|
||||||
context, colorType, nullptr, std::move(renderTarget), kTopLeft_GrSurfaceOrigin,
|
colorType,
|
||||||
nullptr);
|
nullptr,
|
||||||
|
std::move(renderTarget),
|
||||||
|
kTopLeft_GrSurfaceOrigin,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
rtc->drawTexture(nullptr, std::move(mipmapView), alphaType, filter, SkBlendMode::kSrcOver,
|
rtc->drawTexture(nullptr,
|
||||||
{1,1,1,1}, SkRect::MakeWH(4, 4), SkRect::MakeWH(1,1), GrAA::kYes,
|
std::move(mipmapView),
|
||||||
GrQuadAAFlags::kAll, SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(),
|
alphaType,
|
||||||
|
GrSamplerState::Filter::kLinear,
|
||||||
|
mm,
|
||||||
|
SkBlendMode::kSrcOver,
|
||||||
|
{1, 1, 1, 1},
|
||||||
|
SkRect::MakeWH(4, 4),
|
||||||
|
SkRect::MakeWH(1, 1),
|
||||||
|
GrAA::kYes,
|
||||||
|
GrQuadAAFlags::kAll,
|
||||||
|
SkCanvas::kFast_SrcRectConstraint,
|
||||||
|
SkMatrix::I(),
|
||||||
nullptr);
|
nullptr);
|
||||||
return rtc;
|
return rtc;
|
||||||
}
|
}
|
||||||
@ -369,7 +392,7 @@ static std::unique_ptr<GrRenderTargetContext> draw_mipmap_into_new_render_target
|
|||||||
// Test that two opsTasks using the same mipmaps both depend on the same GrTextureResolveRenderTask.
|
// Test that two opsTasks using the same mipmaps both depend on the same GrTextureResolveRenderTask.
|
||||||
DEF_GPUTEST(GrManyDependentsMipMappedTest, reporter, /* options */) {
|
DEF_GPUTEST(GrManyDependentsMipMappedTest, reporter, /* options */) {
|
||||||
using Enable = GrContextOptions::Enable;
|
using Enable = GrContextOptions::Enable;
|
||||||
using Filter = GrSamplerState::Filter;
|
using MipmapMode = GrSamplerState::MipmapMode;
|
||||||
|
|
||||||
for (auto enableSortingAndReduction : {Enable::kYes, Enable::kNo}) {
|
for (auto enableSortingAndReduction : {Enable::kYes, Enable::kNo}) {
|
||||||
GrMockOptions mockOptions;
|
GrMockOptions mockOptions;
|
||||||
@ -421,7 +444,7 @@ DEF_GPUTEST(GrManyDependentsMipMappedTest, reporter, /* options */) {
|
|||||||
|
|
||||||
// Draw the dirty mipmap texture into a render target.
|
// Draw the dirty mipmap texture into a render target.
|
||||||
auto rtc1 = draw_mipmap_into_new_render_target(context.get(), proxyProvider, colorType,
|
auto rtc1 = draw_mipmap_into_new_render_target(context.get(), proxyProvider, colorType,
|
||||||
alphaType, mipmapView, Filter::kMipMap);
|
alphaType, mipmapView, MipmapMode::kLinear);
|
||||||
auto rtc1Task = sk_ref_sp(rtc1->testingOnly_PeekLastOpsTask());
|
auto rtc1Task = sk_ref_sp(rtc1->testingOnly_PeekLastOpsTask());
|
||||||
|
|
||||||
// Mipmaps should have gotten marked dirty during makeClosed, then marked clean again as
|
// Mipmaps should have gotten marked dirty during makeClosed, then marked clean again as
|
||||||
@ -436,7 +459,7 @@ DEF_GPUTEST(GrManyDependentsMipMappedTest, reporter, /* options */) {
|
|||||||
|
|
||||||
// Draw the now-clean mipmap texture into a second target.
|
// Draw the now-clean mipmap texture into a second target.
|
||||||
auto rtc2 = draw_mipmap_into_new_render_target(context.get(), proxyProvider, colorType,
|
auto rtc2 = draw_mipmap_into_new_render_target(context.get(), proxyProvider, colorType,
|
||||||
alphaType, mipmapView, Filter::kMipMap);
|
alphaType, mipmapView, MipmapMode::kLinear);
|
||||||
auto rtc2Task = sk_ref_sp(rtc2->testingOnly_PeekLastOpsTask());
|
auto rtc2Task = sk_ref_sp(rtc2->testingOnly_PeekLastOpsTask());
|
||||||
|
|
||||||
// Make sure the mipmap texture still has the same regen task.
|
// Make sure the mipmap texture still has the same regen task.
|
||||||
@ -465,7 +488,7 @@ DEF_GPUTEST(GrManyDependentsMipMappedTest, reporter, /* options */) {
|
|||||||
|
|
||||||
// Draw the dirty mipmap texture into a render target, but don't do mipmap filtering.
|
// Draw the dirty mipmap texture into a render target, but don't do mipmap filtering.
|
||||||
rtc1 = draw_mipmap_into_new_render_target(context.get(), proxyProvider, colorType,
|
rtc1 = draw_mipmap_into_new_render_target(context.get(), proxyProvider, colorType,
|
||||||
alphaType, mipmapView, Filter::kLinear);
|
alphaType, mipmapView, MipmapMode::kNone);
|
||||||
|
|
||||||
// Mipmaps should have gotten marked dirty during makeClosed() when adding the dependency.
|
// Mipmaps should have gotten marked dirty during makeClosed() when adding the dependency.
|
||||||
// Since the last draw did not use mips, they will not have been regenerated and should
|
// Since the last draw did not use mips, they will not have been regenerated and should
|
||||||
@ -479,7 +502,7 @@ DEF_GPUTEST(GrManyDependentsMipMappedTest, reporter, /* options */) {
|
|||||||
// Draw the stil-dirty mipmap texture into a second target with mipmap filtering.
|
// Draw the stil-dirty mipmap texture into a second target with mipmap filtering.
|
||||||
rtc2 = draw_mipmap_into_new_render_target(context.get(), proxyProvider, colorType,
|
rtc2 = draw_mipmap_into_new_render_target(context.get(), proxyProvider, colorType,
|
||||||
alphaType, std::move(mipmapView),
|
alphaType, std::move(mipmapView),
|
||||||
Filter::kMipMap);
|
MipmapMode::kLinear);
|
||||||
rtc2Task = sk_ref_sp(rtc2->testingOnly_PeekLastOpsTask());
|
rtc2Task = sk_ref_sp(rtc2->testingOnly_PeekLastOpsTask());
|
||||||
|
|
||||||
// Make sure the mipmap texture now has a new last render task that regenerates the mips,
|
// Make sure the mipmap texture now has a new last render task that regenerates the mips,
|
||||||
|
@ -575,11 +575,20 @@ DEF_GPUTEST(TextureIdleProcTest, reporter, options) {
|
|||||||
GrSwizzle readSwizzle = dContext->priv().caps()->getReadSwizzle(
|
GrSwizzle readSwizzle = dContext->priv().caps()->getReadSwizzle(
|
||||||
backendFormat, GrColorType::kRGBA_8888);
|
backendFormat, GrColorType::kRGBA_8888);
|
||||||
GrSurfaceProxyView view(std::move(proxy), kTopLeft_GrSurfaceOrigin, readSwizzle);
|
GrSurfaceProxyView view(std::move(proxy), kTopLeft_GrSurfaceOrigin, readSwizzle);
|
||||||
rtc->drawTexture(nullptr, view, kPremul_SkAlphaType,
|
rtc->drawTexture(nullptr,
|
||||||
GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver,
|
view,
|
||||||
SkPMColor4f(), SkRect::MakeWH(w, h), SkRect::MakeWH(w, h),
|
kPremul_SkAlphaType,
|
||||||
GrAA::kNo, GrQuadAAFlags::kNone, SkCanvas::kFast_SrcRectConstraint,
|
GrSamplerState::Filter::kNearest,
|
||||||
SkMatrix::I(), nullptr);
|
GrSamplerState::MipmapMode::kNone,
|
||||||
|
SkBlendMode::kSrcOver,
|
||||||
|
SkPMColor4f(),
|
||||||
|
SkRect::MakeWH(w, h),
|
||||||
|
SkRect::MakeWH(w, h),
|
||||||
|
GrAA::kNo,
|
||||||
|
GrQuadAAFlags::kNone,
|
||||||
|
SkCanvas::kFast_SrcRectConstraint,
|
||||||
|
SkMatrix::I(),
|
||||||
|
nullptr);
|
||||||
// We still have the proxy, which should remain instantiated, thereby keeping the
|
// We still have the proxy, which should remain instantiated, thereby keeping the
|
||||||
// texture not purgeable.
|
// texture not purgeable.
|
||||||
REPORTER_ASSERT(reporter, idleIDs.find(2) == idleIDs.end());
|
REPORTER_ASSERT(reporter, idleIDs.find(2) == idleIDs.end());
|
||||||
@ -589,11 +598,20 @@ DEF_GPUTEST(TextureIdleProcTest, reporter, options) {
|
|||||||
REPORTER_ASSERT(reporter, idleIDs.find(2) == idleIDs.end());
|
REPORTER_ASSERT(reporter, idleIDs.find(2) == idleIDs.end());
|
||||||
|
|
||||||
// This time we move the proxy into the draw.
|
// This time we move the proxy into the draw.
|
||||||
rtc->drawTexture(nullptr, std::move(view), kPremul_SkAlphaType,
|
rtc->drawTexture(nullptr,
|
||||||
GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver,
|
std::move(view),
|
||||||
SkPMColor4f(), SkRect::MakeWH(w, h), SkRect::MakeWH(w, h),
|
kPremul_SkAlphaType,
|
||||||
GrAA::kNo, GrQuadAAFlags::kNone,
|
GrSamplerState::Filter::kNearest,
|
||||||
SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(), nullptr);
|
GrSamplerState::MipmapMode::kNone,
|
||||||
|
SkBlendMode::kSrcOver,
|
||||||
|
SkPMColor4f(),
|
||||||
|
SkRect::MakeWH(w, h),
|
||||||
|
SkRect::MakeWH(w, h),
|
||||||
|
GrAA::kNo,
|
||||||
|
GrQuadAAFlags::kNone,
|
||||||
|
SkCanvas::kFast_SrcRectConstraint,
|
||||||
|
SkMatrix::I(),
|
||||||
|
nullptr);
|
||||||
REPORTER_ASSERT(reporter, idleIDs.find(2) == idleIDs.end());
|
REPORTER_ASSERT(reporter, idleIDs.find(2) == idleIDs.end());
|
||||||
dContext->flushAndSubmit();
|
dContext->flushAndSubmit();
|
||||||
dContext->priv().getGpu()->testingOnly_flushGpuAndSync();
|
dContext->priv().getGpu()->testingOnly_flushGpuAndSync();
|
||||||
@ -640,12 +658,20 @@ DEF_GPUTEST(TextureIdleProcTest, reporter, options) {
|
|||||||
proxy->backendFormat(), GrColorType::kRGBA_8888);
|
proxy->backendFormat(), GrColorType::kRGBA_8888);
|
||||||
GrSurfaceProxyView view(std::move(proxy), kTopLeft_GrSurfaceOrigin,
|
GrSurfaceProxyView view(std::move(proxy), kTopLeft_GrSurfaceOrigin,
|
||||||
swizzle);
|
swizzle);
|
||||||
rtc->drawTexture(
|
rtc->drawTexture(nullptr,
|
||||||
nullptr, std::move(view), kPremul_SkAlphaType,
|
std::move(view),
|
||||||
GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver,
|
kPremul_SkAlphaType,
|
||||||
SkPMColor4f(), SkRect::MakeWH(w, h), SkRect::MakeWH(w, h),
|
GrSamplerState::Filter::kNearest,
|
||||||
GrAA::kNo, GrQuadAAFlags::kNone,
|
GrSamplerState::MipmapMode::kNone,
|
||||||
SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(), nullptr);
|
SkBlendMode::kSrcOver,
|
||||||
|
SkPMColor4f(),
|
||||||
|
SkRect::MakeWH(w, h),
|
||||||
|
SkRect::MakeWH(w, h),
|
||||||
|
GrAA::kNo,
|
||||||
|
GrQuadAAFlags::kNone,
|
||||||
|
SkCanvas::kFast_SrcRectConstraint,
|
||||||
|
SkMatrix::I(),
|
||||||
|
nullptr);
|
||||||
if (drawType == DrawType::kDrawAndFlush) {
|
if (drawType == DrawType::kDrawAndFlush) {
|
||||||
dContext->flushAndSubmit();
|
dContext->flushAndSubmit();
|
||||||
}
|
}
|
||||||
|
@ -28,17 +28,17 @@ static void test_basic_draw_as_src(skiatest::Reporter* reporter, GrRecordingCont
|
|||||||
SkAlphaType alphaType, uint32_t expectedPixelValues[]) {
|
SkAlphaType alphaType, uint32_t expectedPixelValues[]) {
|
||||||
auto rtContext = GrRenderTargetContext::Make(
|
auto rtContext = GrRenderTargetContext::Make(
|
||||||
context, colorType, nullptr, SkBackingFit::kExact, rectView.proxy()->dimensions());
|
context, colorType, nullptr, SkBackingFit::kExact, rectView.proxy()->dimensions());
|
||||||
for (auto filter : {GrSamplerState::Filter::kNearest,
|
for (auto filter : {GrSamplerState::Filter::kNearest, GrSamplerState::Filter::kLinear}) {
|
||||||
GrSamplerState::Filter::kLinear,
|
for (auto mm : {GrSamplerState::MipmapMode::kNone, GrSamplerState::MipmapMode::kLinear}) {
|
||||||
GrSamplerState::Filter::kMipMap}) {
|
rtContext->clear(SkPMColor4f::FromBytes_RGBA(0xDDCCBBAA));
|
||||||
rtContext->clear(SkPMColor4f::FromBytes_RGBA(0xDDCCBBAA));
|
auto fp = GrTextureEffect::Make(rectView, alphaType, SkMatrix::I(), filter, mm);
|
||||||
auto fp = GrTextureEffect::Make(rectView, alphaType, SkMatrix::I(), filter);
|
GrPaint paint;
|
||||||
GrPaint paint;
|
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
|
||||||
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
|
paint.setColorFragmentProcessor(std::move(fp));
|
||||||
paint.setColorFragmentProcessor(std::move(fp));
|
rtContext->drawPaint(nullptr, std::move(paint), SkMatrix::I());
|
||||||
rtContext->drawPaint(nullptr, std::move(paint), SkMatrix::I());
|
TestReadPixels(reporter, rtContext.get(), expectedPixelValues,
|
||||||
TestReadPixels(reporter, rtContext.get(), expectedPixelValues,
|
"RectangleTexture-basic-draw");
|
||||||
"RectangleTexture-basic-draw");
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user