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->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, false, 0));
|
||||
topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, true, 100));
|
||||
rtc->drawTexture(nullptr, topLeftRTC->readSurfaceView(), rtc->colorInfo().alphaType(),
|
||||
GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver, SK_PMColor4fWHITE,
|
||||
{0, 0, 100, 200}, {100, 0, 200, 200}, GrAA::kNo, GrQuadAAFlags::kNone,
|
||||
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, SkMatrix::I(),
|
||||
rtc->drawTexture(nullptr,
|
||||
topLeftRTC->readSurfaceView(),
|
||||
rtc->colorInfo().alphaType(),
|
||||
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);
|
||||
}
|
||||
|
||||
@ -269,10 +278,19 @@ void ClockwiseGM::onDraw(GrRecordingContext* ctx, GrRenderTargetContext* rtc, Sk
|
||||
topLeftRTC->clear(SK_PMColor4fTRANSPARENT);
|
||||
topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, false, 0));
|
||||
topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, true, 100));
|
||||
rtc->drawTexture(nullptr, topLeftRTC->readSurfaceView(), rtc->colorInfo().alphaType(),
|
||||
GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver, SK_PMColor4fWHITE,
|
||||
{0, 0, 100, 200}, {200, 0, 300, 200}, GrAA::kNo, GrQuadAAFlags::kNone,
|
||||
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, SkMatrix::I(),
|
||||
rtc->drawTexture(nullptr,
|
||||
topLeftRTC->readSurfaceView(),
|
||||
rtc->colorInfo().alphaType(),
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -366,11 +366,19 @@ DrawResult SampleLocationsGM::onDraw(GrRecordingContext* ctx, GrRenderTargetCont
|
||||
SkMatrix::I(), SkRect::MakeWH(200, 200));
|
||||
|
||||
// Copy offscreen texture to canvas.
|
||||
rtc->drawTexture(nullptr, offscreenRTC->readSurfaceView(),
|
||||
rtc->drawTexture(nullptr,
|
||||
offscreenRTC->readSurfaceView(),
|
||||
offscreenRTC->colorInfo().alphaType(),
|
||||
GrSamplerState::Filter::kNearest, SkBlendMode::kSrc, SK_PMColor4fWHITE,
|
||||
{0,0,200,200}, {0,0,200,200}, GrAA::kNo, GrQuadAAFlags::kNone,
|
||||
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, SkMatrix::I(),
|
||||
GrSamplerState::Filter::kNearest,
|
||||
GrSamplerState::MipmapMode::kNone,
|
||||
SkBlendMode::kSrc,
|
||||
SK_PMColor4fWHITE,
|
||||
{0, 0, 200, 200},
|
||||
{0, 0, 200, 200},
|
||||
GrAA::kNo,
|
||||
GrQuadAAFlags::kNone,
|
||||
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint,
|
||||
SkMatrix::I(),
|
||||
nullptr);
|
||||
|
||||
return skiagm::DrawResult::kOk;
|
||||
|
@ -33,28 +33,37 @@
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
using MipmapMode = GrSamplerState::MipmapMode;
|
||||
using Filter = GrSamplerState::Filter;
|
||||
using Wrap = GrSamplerState::WrapMode;
|
||||
|
||||
namespace skiagm {
|
||||
/**
|
||||
* This GM directly exercises GrTextureEffect::MakeTexelSubset.
|
||||
*/
|
||||
class TexelSubset : public GpuGM {
|
||||
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);
|
||||
}
|
||||
|
||||
protected:
|
||||
SkString onShortName() override {
|
||||
SkString name("texel_subset");
|
||||
switch (fMipmapMode) {
|
||||
case MipmapMode::kNone:
|
||||
break;
|
||||
case MipmapMode::kLinear:
|
||||
name.append("_linear_mipmap");
|
||||
break;
|
||||
}
|
||||
switch (fFilter) {
|
||||
case GrSamplerState::Filter::kNearest:
|
||||
case Filter::kNearest:
|
||||
name.append("_nearest");
|
||||
break;
|
||||
case GrSamplerState::Filter::kLinear:
|
||||
name.append("_bilerp");
|
||||
break;
|
||||
case GrSamplerState::Filter::kMipMap:
|
||||
name.append("_mip_map");
|
||||
case Filter::kLinear:
|
||||
name.append("_linear");
|
||||
break;
|
||||
}
|
||||
name.append(fUpscale ? "_up" : "_down");
|
||||
@ -77,11 +86,13 @@ protected:
|
||||
|
||||
DrawResult onDraw(GrRecordingContext* context, GrRenderTargetContext* renderTargetContext,
|
||||
SkCanvas* canvas, SkString* errorMsg) override {
|
||||
GrMipmapped mipMapped = fFilter == GrSamplerState::Filter::kMipMap &&
|
||||
context->priv().caps()->mipmapSupport()
|
||||
? GrMipmapped::kYes : GrMipmapped::kNo;
|
||||
GrMipmapped mipmapped = (fMipmapMode != MipmapMode::kNone) ? GrMipmapped::kYes
|
||||
: GrMipmapped::kNo;
|
||||
if (mipmapped == GrMipmapped::kYes && !context->priv().caps()->mipmapSupport()) {
|
||||
return DrawResult::kSkip;
|
||||
}
|
||||
GrBitmapTextureMaker maker(context, fBitmap, GrImageTexGenPolicy::kDraw);
|
||||
auto view = maker.view(mipMapped);
|
||||
auto view = maker.view(mipmapped);
|
||||
if (!view) {
|
||||
*errorMsg = "Failed to create proxy.";
|
||||
return DrawResult::kFail;
|
||||
@ -115,7 +126,7 @@ protected:
|
||||
fBitmap.extractSubset(&subsetBmp, texelSubset);
|
||||
subsetBmp.setImmutable();
|
||||
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);
|
||||
|
||||
@ -126,13 +137,13 @@ protected:
|
||||
for (int tm = 0; tm < textureMatrices.count(); ++tm) {
|
||||
for (int my = 0; my < GrSamplerState::kWrapModeCount; ++my) {
|
||||
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) {
|
||||
auto wmx = static_cast<GrSamplerState::WrapMode>(mx);
|
||||
auto wmx = static_cast<Wrap>(mx);
|
||||
|
||||
const auto& caps = *context->priv().caps();
|
||||
|
||||
GrSamplerState sampler(wmx, wmy, fFilter);
|
||||
GrSamplerState sampler(wmx, wmy, fFilter, fMipmapMode);
|
||||
|
||||
drawRect = localRect.makeOffset(x, y);
|
||||
|
||||
@ -166,9 +177,11 @@ protected:
|
||||
SkMatrix subsetTextureMatrix = SkMatrix::Concat(
|
||||
SkMatrix::Translate(-texelSubset.topLeft()), textureMatrices[tm]);
|
||||
|
||||
auto fp2 = GrTextureEffect::Make(subsetView, fBitmap.alphaType(),
|
||||
auto fp2 = GrTextureEffect::Make(subsetView,
|
||||
fBitmap.alphaType(),
|
||||
subsetTextureMatrix,
|
||||
GrSamplerState(wmx, wmy, fFilter), caps);
|
||||
sampler,
|
||||
caps);
|
||||
if (auto op = sk_gpu_test::test_ops::MakeRect(context, std::move(fp2), drawRect,
|
||||
localRect)) {
|
||||
renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
|
||||
@ -202,17 +215,19 @@ private:
|
||||
static constexpr SkScalar kDrawPad = 10.f;
|
||||
static constexpr SkScalar kTestPad = 10.f;
|
||||
SkBitmap fBitmap;
|
||||
GrSamplerState::Filter fFilter;
|
||||
Filter fFilter;
|
||||
MipmapMode fMipmapMode;
|
||||
bool fUpscale;
|
||||
|
||||
typedef GM INHERITED;
|
||||
};
|
||||
|
||||
DEF_GM(return new TexelSubset(GrSamplerState::Filter::kNearest, false);)
|
||||
DEF_GM(return new TexelSubset(GrSamplerState::Filter::kNearest, true);)
|
||||
DEF_GM(return new TexelSubset(GrSamplerState::Filter::kLinear , false);)
|
||||
DEF_GM(return new TexelSubset(GrSamplerState::Filter::kLinear , true);)
|
||||
DEF_GM(return new TexelSubset(Filter::kNearest, MipmapMode::kNone , false);)
|
||||
DEF_GM(return new TexelSubset(Filter::kNearest, MipmapMode::kNone , true);)
|
||||
DEF_GM(return new TexelSubset(Filter::kLinear , MipmapMode::kNone , false);)
|
||||
DEF_GM(return new TexelSubset(Filter::kLinear , MipmapMode::kNone , true);)
|
||||
// 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 {
|
||||
this->visitTextureEffects([&func](const GrTextureEffect& te) {
|
||||
bool mipped = (GrSamplerState::Filter::kMipMap == te.samplerState().filter());
|
||||
func(te.view().proxy(), GrMipmapped(mipped));
|
||||
func(te.view().proxy(), te.samplerState().mipmapped());
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
// If not, fall back to linear filtering. Also fall back to linear filtering when a domain is
|
||||
// requested.
|
||||
if (samplerState.filter() == GrSamplerState::Filter::kMipMap &&
|
||||
// If not disable mip mapping. Also disable when a subset is requested.
|
||||
if (samplerState.mipmapped() == GrMipmapped::kYes &&
|
||||
(subset || !fImage->setupMipmapsForPlanes(this->context()))) {
|
||||
samplerState.setFilterMode(GrSamplerState::Filter::kLinear);
|
||||
samplerState.setMipmapMode(GrSamplerState::MipmapMode::kNone);
|
||||
}
|
||||
|
||||
const auto& caps = *fImage->context()->priv().caps();
|
||||
|
@ -158,7 +158,7 @@ void GrOpsRenderPass::bindTextures(const GrPrimitiveProcessor& primProc,
|
||||
|
||||
const GrTexture* tex = proxy->peekTexture();
|
||||
SkASSERT(tex);
|
||||
if (GrSamplerState::Filter::kMipMap == sampler.samplerState().filter() &&
|
||||
if (sampler.samplerState().mipmapped() == GrMipmapped::kYes &&
|
||||
(tex->width() != 1 || tex->height() != 1)) {
|
||||
// There are some cases where we might be given a non-mipmapped texture with a mipmap
|
||||
// filter. See skbug.com/7094.
|
||||
|
@ -43,7 +43,7 @@ void GrProgramInfo::checkMSAAAndMIPSAreResolved() const {
|
||||
SkASSERT(tex);
|
||||
|
||||
// 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)) {
|
||||
// There are some cases where we might be given a non-mipmapped texture with a
|
||||
// mipmap filter. See skbug.com/7094.
|
||||
|
@ -798,6 +798,7 @@ void GrRenderTargetContext::drawTexturedQuad(const GrClip* clip,
|
||||
SkAlphaType srcAlphaType,
|
||||
sk_sp<GrColorSpaceXform> textureXform,
|
||||
GrSamplerState::Filter filter,
|
||||
GrSamplerState::MipmapMode mm,
|
||||
const SkPMColor4f& color,
|
||||
SkBlendMode blendMode,
|
||||
GrAA aa,
|
||||
@ -827,7 +828,7 @@ void GrRenderTargetContext::drawTexturedQuad(const GrClip* clip,
|
||||
// quad is sufficiently inside the subset and the constraint could be dropped.
|
||||
this->addDrawOp(finalClip,
|
||||
GrTextureOp::Make(fContext, std::move(proxyView), srcAlphaType,
|
||||
std::move(textureXform), filter, color, saturate,
|
||||
std::move(textureXform), filter, mm, color, saturate,
|
||||
blendMode, aaType, quad, subset));
|
||||
}
|
||||
}
|
||||
@ -1007,10 +1008,15 @@ void GrRenderTargetContextPriv::stencilPath(const GrHardClip* clip,
|
||||
fRenderTargetContext->addOp(std::move(op));
|
||||
}
|
||||
|
||||
void GrRenderTargetContext::drawTextureSet(const GrClip* clip, TextureSetEntry set[],
|
||||
int cnt, int proxyRunCnt,
|
||||
GrSamplerState::Filter filter, SkBlendMode mode,
|
||||
GrAA aa, SkCanvas::SrcRectConstraint constraint,
|
||||
void GrRenderTargetContext::drawTextureSet(const GrClip* clip,
|
||||
TextureSetEntry set[],
|
||||
int cnt,
|
||||
int proxyRunCnt,
|
||||
GrSamplerState::Filter filter,
|
||||
GrSamplerState::MipmapMode mm,
|
||||
SkBlendMode mode,
|
||||
GrAA aa,
|
||||
SkCanvas::SrcRectConstraint constraint,
|
||||
const SkMatrix& viewMatrix,
|
||||
sk_sp<GrColorSpaceXform> texXform) {
|
||||
ASSERT_SINGLE_OWNER
|
||||
@ -1025,7 +1031,7 @@ void GrRenderTargetContext::drawTextureSet(const GrClip* clip, TextureSetEntry s
|
||||
auto clampType = GrColorTypeClampType(this->colorInfo().colorType());
|
||||
auto saturate = clampType == GrClampType::kManual ? GrTextureOp::Saturate::kYes
|
||||
: 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));
|
||||
}
|
||||
|
||||
|
@ -270,17 +270,26 @@ public:
|
||||
* specifies the rectangle to draw in local coords which will be transformed by 'viewMatrix' to
|
||||
* device space.
|
||||
*/
|
||||
void drawTexture(const GrClip* clip, GrSurfaceProxyView view, SkAlphaType srcAlphaType,
|
||||
GrSamplerState::Filter filter, SkBlendMode mode, const SkPMColor4f& color,
|
||||
const SkRect& srcRect, const SkRect& dstRect, GrAA aa, GrQuadAAFlags edgeAA,
|
||||
SkCanvas::SrcRectConstraint constraint, const SkMatrix& viewMatrix,
|
||||
void drawTexture(const GrClip* clip,
|
||||
GrSurfaceProxyView view,
|
||||
SkAlphaType srcAlphaType,
|
||||
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) {
|
||||
const SkRect* subset = constraint == SkCanvas::kStrict_SrcRectConstraint ?
|
||||
&srcRect : nullptr;
|
||||
DrawQuad quad{GrQuad::MakeFromRect(dstRect, viewMatrix), GrQuad(srcRect), edgeAA};
|
||||
|
||||
this->drawTexturedQuad(clip, std::move(view), srcAlphaType, std::move(texXform),
|
||||
filter, color, mode, aa, &quad, subset);
|
||||
this->drawTexturedQuad(clip, std::move(view), srcAlphaType, std::move(texXform), filter, mm,
|
||||
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
|
||||
* provided, the strict src rect constraint is applied using 'subset'.
|
||||
*/
|
||||
void drawTextureQuad(const GrClip* clip, GrSurfaceProxyView view, GrColorType srcColorType,
|
||||
SkAlphaType srcAlphaType, GrSamplerState::Filter filter, SkBlendMode mode,
|
||||
const SkPMColor4f& color, const SkPoint srcQuad[4],
|
||||
const SkPoint dstQuad[4], GrAA aa, GrQuadAAFlags edgeAA,
|
||||
const SkRect* subset, const SkMatrix& viewMatrix,
|
||||
void drawTextureQuad(const GrClip* clip,
|
||||
GrSurfaceProxyView view,
|
||||
GrColorType srcColorType,
|
||||
SkAlphaType srcAlphaType,
|
||||
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) {
|
||||
DrawQuad quad{GrQuad::MakeFromSkQuad(dstQuad, viewMatrix),
|
||||
GrQuad::MakeFromSkQuad(srcQuad, SkMatrix::I()), edgeAA};
|
||||
this->drawTexturedQuad(clip, std::move(view), srcAlphaType, std::move(texXform),
|
||||
filter, color, mode, aa, &quad, subset);
|
||||
this->drawTexturedQuad(clip, std::move(view), srcAlphaType, std::move(texXform), filter, mm,
|
||||
color, mode, aa, &quad, subset);
|
||||
}
|
||||
|
||||
/** Used with drawTextureSet */
|
||||
@ -323,9 +341,16 @@ public:
|
||||
* 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.
|
||||
*/
|
||||
void drawTextureSet(const GrClip*, TextureSetEntry[], int cnt, int proxyRunCnt,
|
||||
GrSamplerState::Filter, SkBlendMode mode, GrAA aa,
|
||||
SkCanvas::SrcRectConstraint, const SkMatrix& viewMatrix,
|
||||
void drawTextureSet(const GrClip*,
|
||||
TextureSetEntry[],
|
||||
int cnt,
|
||||
int proxyRunCnt,
|
||||
GrSamplerState::Filter,
|
||||
GrSamplerState::MipmapMode,
|
||||
SkBlendMode mode,
|
||||
GrAA aa,
|
||||
SkCanvas::SrcRectConstraint,
|
||||
const SkMatrix& viewMatrix,
|
||||
sk_sp<GrColorSpaceXform> texXform);
|
||||
|
||||
/**
|
||||
@ -645,6 +670,7 @@ private:
|
||||
SkAlphaType alphaType,
|
||||
sk_sp<GrColorSpaceXform> textureXform,
|
||||
GrSamplerState::Filter filter,
|
||||
GrSamplerState::MipmapMode,
|
||||
const SkPMColor4f& color,
|
||||
SkBlendMode blendMode,
|
||||
GrAA aa,
|
||||
|
@ -16,48 +16,71 @@
|
||||
*/
|
||||
class GrSamplerState {
|
||||
public:
|
||||
enum class Filter : uint8_t { kNearest, kLinear, kMipMap, kLast = kMipMap };
|
||||
enum class WrapMode : uint8_t { kClamp, kRepeat, kMirrorRepeat, kClampToBorder,
|
||||
kLast = kClampToBorder };
|
||||
enum class Filter : uint8_t { kNearest, kLinear, kLast = kLinear };
|
||||
enum class MipmapMode : uint8_t { kNone, /*kNearest,*/ kLinear, kLast = kLinear };
|
||||
|
||||
enum class WrapMode : uint8_t {
|
||||
kClamp,
|
||||
kRepeat,
|
||||
kMirrorRepeat,
|
||||
kClampToBorder,
|
||||
kLast = kClampToBorder
|
||||
};
|
||||
|
||||
static constexpr int kFilterCount = static_cast<int>(Filter::kLast) + 1;
|
||||
static constexpr int kWrapModeCount = static_cast<int>(WrapMode::kLast) + 1;
|
||||
|
||||
constexpr GrSamplerState() = default;
|
||||
|
||||
constexpr GrSamplerState(WrapMode wrapXAndY, Filter filter)
|
||||
: fWrapModes{wrapXAndY, wrapXAndY}, fFilter(filter) {}
|
||||
constexpr GrSamplerState(WrapMode wrapXAndY, Filter filter, MipmapMode mm = MipmapMode::kNone)
|
||||
: fWrapModes{wrapXAndY, wrapXAndY}, fFilter(filter), fMipmapMode(mm) {}
|
||||
|
||||
constexpr GrSamplerState(WrapMode wrapX, WrapMode wrapY, Filter filter)
|
||||
: fWrapModes{wrapX, wrapY}, fFilter(filter) {}
|
||||
constexpr GrSamplerState(WrapMode wrapX,
|
||||
WrapMode wrapY,
|
||||
Filter filter,
|
||||
MipmapMode mm = MipmapMode::kNone)
|
||||
: fWrapModes{wrapX, wrapY}, fFilter(filter), fMipmapMode(mm) {}
|
||||
|
||||
constexpr GrSamplerState(const WrapMode wrapModes[2], Filter filter)
|
||||
: fWrapModes{wrapModes[0], wrapModes[1]}, fFilter(filter) {}
|
||||
constexpr GrSamplerState(const WrapMode wrapModes[2],
|
||||
Filter filter,
|
||||
MipmapMode mm = MipmapMode::kNone)
|
||||
: fWrapModes{wrapModes[0], wrapModes[1]}, fFilter(filter), fMipmapMode(mm) {}
|
||||
|
||||
constexpr /*explicit*/ GrSamplerState(Filter filter) : fFilter(filter) {}
|
||||
constexpr GrSamplerState(Filter filter, MipmapMode mm) : fFilter(filter), fMipmapMode(mm) {}
|
||||
|
||||
constexpr GrSamplerState(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 wrapModeY() const { return fWrapModes[1]; }
|
||||
|
||||
constexpr bool isRepeated() const {
|
||||
return (WrapMode::kClamp != fWrapModes[0] && WrapMode::kClampToBorder != fWrapModes[0]) ||
|
||||
(WrapMode::kClamp != fWrapModes[1] && WrapMode::kClampToBorder != fWrapModes[1]);
|
||||
return fWrapModes[0] == WrapMode::kRepeat || fWrapModes[0] == WrapMode::kMirrorRepeat ||
|
||||
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 {
|
||||
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); }
|
||||
@ -68,19 +91,23 @@ public:
|
||||
*/
|
||||
constexpr uint8_t asIndex() const {
|
||||
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
|
||||
+ 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);
|
||||
return static_cast<uint8_t>(result);
|
||||
}
|
||||
|
||||
static constexpr int kNumUniqueSamplers = (static_cast<int>(WrapMode::kLast) + 1)
|
||||
* (static_cast<int>(WrapMode::kLast) + 1)
|
||||
* (static_cast<int>(Filter::kLast ) + 1);
|
||||
static constexpr int kNumUniqueSamplers = (static_cast<int>(WrapMode::kLast ) + 1)
|
||||
* (static_cast<int>(WrapMode::kLast ) + 1)
|
||||
* (static_cast<int>(Filter::kLast ) + 1)
|
||||
* (static_cast<int>(MipmapMode::kLast) + 1);
|
||||
private:
|
||||
WrapMode fWrapModes[2] = {WrapMode::kClamp, WrapMode::kClamp};
|
||||
Filter fFilter = GrSamplerState::Filter::kNearest;
|
||||
MipmapMode fMipmapMode = GrSamplerState::MipmapMode::kNone;
|
||||
};
|
||||
|
||||
static_assert(GrSamplerState::kNumUniqueSamplers <=
|
||||
|
@ -575,12 +575,20 @@ void GrSurfaceContext::asyncRescaleAndReadPixels(const SkImageInfo& info,
|
||||
callback(context, nullptr);
|
||||
return;
|
||||
}
|
||||
tempRTC->drawTexture(nullptr, std::move(texProxyView), this->colorInfo().alphaType(),
|
||||
GrSamplerState::Filter::kNearest, SkBlendMode::kSrc,
|
||||
SK_PMColor4fWHITE, srcRectToDraw,
|
||||
SkRect::MakeWH(srcRect.width(), srcRect.height()), GrAA::kNo,
|
||||
GrQuadAAFlags::kNone, SkCanvas::kFast_SrcRectConstraint,
|
||||
SkMatrix::I(), std::move(xform));
|
||||
tempRTC->drawTexture(nullptr,
|
||||
std::move(texProxyView),
|
||||
this->colorInfo().alphaType(),
|
||||
GrSamplerState::Filter::kNearest,
|
||||
GrSamplerState::MipmapMode::kNone,
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -799,11 +807,20 @@ void GrSurfaceContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorS
|
||||
callback(context, nullptr);
|
||||
return;
|
||||
}
|
||||
tempRTC->drawTexture(nullptr, std::move(srcView), this->colorInfo().alphaType(),
|
||||
GrSamplerState::Filter::kNearest, SkBlendMode::kSrc,
|
||||
SK_PMColor4fWHITE, srcRectToDraw, SkRect::Make(srcRect.size()),
|
||||
GrAA::kNo, GrQuadAAFlags::kNone, SkCanvas::kFast_SrcRectConstraint,
|
||||
SkMatrix::I(), std::move(xform));
|
||||
tempRTC->drawTexture(nullptr,
|
||||
std::move(srcView),
|
||||
this->colorInfo().alphaType(),
|
||||
GrSamplerState::Filter::kNearest,
|
||||
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();
|
||||
SkASSERT(srcView.asTextureProxy());
|
||||
x = y = 0;
|
||||
@ -1058,11 +1075,20 @@ std::unique_ptr<GrRenderTargetContext> GrSurfaceContext::rescale(const GrImageIn
|
||||
return nullptr;
|
||||
}
|
||||
// 1-to-1 draw can always be kFast.
|
||||
linearRTC->drawTexture(nullptr, std::move(texView), srcAlphaType,
|
||||
GrSamplerState::Filter::kNearest, SkBlendMode::kSrc,
|
||||
SK_PMColor4fWHITE, SkRect::Make(srcRect),
|
||||
SkRect::Make(srcRect.size()), GrAA::kNo, GrQuadAAFlags::kNone,
|
||||
SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(), std::move(xform));
|
||||
linearRTC->drawTexture(nullptr,
|
||||
std::move(texView),
|
||||
srcAlphaType,
|
||||
GrSamplerState::Filter::kNearest,
|
||||
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();
|
||||
SkASSERT(texView.asTextureProxy());
|
||||
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()) {
|
||||
constraint = SkCanvas::SrcRectConstraint::kFast_SrcRectConstraint;
|
||||
}
|
||||
tempB->drawTexture(nullptr, std::move(texView), srcAlphaType, filter, SkBlendMode::kSrc,
|
||||
SK_PMColor4fWHITE, SkRect::Make(srcRect), dstRect, GrAA::kNo,
|
||||
GrQuadAAFlags::kNone, constraint, SkMatrix::I(), std::move(xform));
|
||||
tempB->drawTexture(nullptr,
|
||||
std::move(texView),
|
||||
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();
|
||||
tempA = std::move(tempB);
|
||||
|
@ -81,7 +81,7 @@ std::unique_ptr<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor(
|
||||
const SkRect* domain,
|
||||
GrSamplerState samplerState) {
|
||||
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(
|
||||
|
@ -29,7 +29,7 @@ std::unique_ptr<GrFragmentProcessor> GrTextureMaker::createFragmentProcessor(
|
||||
GrSamplerState sampler) {
|
||||
GrSurfaceProxyView view;
|
||||
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(
|
||||
|
@ -101,9 +101,3 @@ GrSurfaceProxyView GrTextureProducer::view(GrMipmapped mipMapped) {
|
||||
!caps->isFormatCopyable(result.proxy()->backendFormat()));
|
||||
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);
|
||||
|
||||
/** Helper version of above that determines MIP mapping requirement from Filter. */
|
||||
GrSurfaceProxyView view(GrSamplerState::Filter);
|
||||
|
||||
int width() const { return fImageInfo.width(); }
|
||||
int height() const { return fImageInfo.height(); }
|
||||
SkISize dimensions() const { return fImageInfo.dimensions(); }
|
||||
|
@ -147,11 +147,6 @@ size_t GrTextureProxy::onUninstantiatedGpuMemorySize(const GrCaps& caps) const {
|
||||
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,
|
||||
const GrSurfaceProxy* second) {
|
||||
// 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());
|
||||
}
|
||||
|
||||
// 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
|
||||
// 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
|
||||
|
@ -817,7 +817,6 @@ static GrSamplerState::Filter compute_lattice_filter_mode(const SkPaint& paint)
|
||||
if (paint.getFilterQuality() == kNone_SkFilterQuality) {
|
||||
return GrSamplerState::Filter::kNearest;
|
||||
}
|
||||
|
||||
return GrSamplerState::Filter::kLinear;
|
||||
}
|
||||
|
||||
@ -861,7 +860,7 @@ void SkGpuDevice::drawProducerLattice(GrTextureProducer* producer,
|
||||
|
||||
auto dstColorSpace = fRenderTargetContext->colorInfo().colorSpace();
|
||||
const GrSamplerState::Filter filter = compute_lattice_filter_mode(*paint);
|
||||
auto view = producer->view(filter);
|
||||
auto view = producer->view(GrMipmapped::kNo);
|
||||
if (!view) {
|
||||
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
|
||||
static void draw_texture(GrRenderTargetContext* rtc, const GrClip* clip, const SkMatrix& ctm,
|
||||
const SkPaint& paint, const SkRect& srcRect, const SkRect& dstRect,
|
||||
const SkPoint dstClip[4], GrAA aa, GrQuadAAFlags aaFlags,
|
||||
SkCanvas::SrcRectConstraint constraint, GrSurfaceProxyView view,
|
||||
static void draw_texture(GrRenderTargetContext* rtc,
|
||||
const GrClip* clip,
|
||||
const SkMatrix& ctm,
|
||||
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& dstInfo(rtc->colorInfo());
|
||||
auto textureXform =
|
||||
@ -378,15 +385,36 @@ static void draw_texture(GrRenderTargetContext* rtc, const GrClip* clip, const S
|
||||
SkPoint srcQuad[4];
|
||||
GrMapRectPoints(dstRect, srcRect, dstClip, srcQuad, 4);
|
||||
|
||||
rtc->drawTextureQuad(clip, std::move(view), srcColorInfo.colorType(),
|
||||
srcColorInfo.alphaType(), filter, paint.getBlendMode(), color, srcQuad,
|
||||
dstClip, aa, aaFlags,
|
||||
rtc->drawTextureQuad(clip,
|
||||
std::move(view),
|
||||
srcColorInfo.colorType(),
|
||||
srcColorInfo.alphaType(),
|
||||
filter,
|
||||
GrSamplerState::MipmapMode::kNone,
|
||||
paint.getBlendMode(),
|
||||
color,
|
||||
srcQuad,
|
||||
dstClip,
|
||||
aa,
|
||||
aaFlags,
|
||||
constraint == SkCanvas::kStrict_SrcRectConstraint ? &srcRect : nullptr,
|
||||
ctm, std::move(textureXform));
|
||||
ctm,
|
||||
std::move(textureXform));
|
||||
} else {
|
||||
rtc->drawTexture(clip, std::move(view), srcColorInfo.alphaType(), filter,
|
||||
paint.getBlendMode(), color, srcRect, dstRect, aa, aaFlags, constraint,
|
||||
ctm, std::move(textureXform));
|
||||
rtc->drawTexture(clip,
|
||||
std::move(view),
|
||||
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,
|
||||
GrQuadAAFlags aaFlags,
|
||||
SkCanvas::SrcRectConstraint constraint,
|
||||
GrSamplerState::WrapMode wm,
|
||||
GrSamplerState::Filter fm,
|
||||
GrSamplerState sampler,
|
||||
bool doBicubic) {
|
||||
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)) {
|
||||
// We've done enough checks above to allow us to pass ClampNearest() and not check for
|
||||
// scaling adjustments.
|
||||
@ -446,8 +474,9 @@ static void draw_texture_producer(GrRecordingContext* context,
|
||||
bool coordsAllInsideSrcRect = aaFlags == GrQuadAAFlags::kNone && !mf;
|
||||
|
||||
// Check for optimization to drop the src rect constraint when using linear filtering.
|
||||
if (!doBicubic && fm == GrSamplerState::Filter::kLinear && restrictToSubset &&
|
||||
coordsAllInsideSrcRect && !producer->isPlanar()) {
|
||||
if (!doBicubic && sampler.filter() == GrSamplerState::Filter::kLinear && restrictToSubset &&
|
||||
sampler.mipmapped() == GrMipmapped::kNo && coordsAllInsideSrcRect &&
|
||||
!producer->isPlanar()) {
|
||||
SkMatrix combinedMatrix;
|
||||
combinedMatrix.setConcat(ctm, srcToDst);
|
||||
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;
|
||||
std::unique_ptr<GrFragmentProcessor> fp;
|
||||
if (doBicubic) {
|
||||
fp = producer->createBicubicFragmentProcessor(textureMatrix, subset, domain, wm, wm);
|
||||
fp = producer->createBicubicFragmentProcessor(textureMatrix, subset, domain,
|
||||
sampler.wrapModeX(), sampler.wrapModeY());
|
||||
} else {
|
||||
fp = producer->createFragmentProcessor(textureMatrix, subset, domain, {wm, fm});
|
||||
fp = producer->createFragmentProcessor(textureMatrix, subset, domain, sampler);
|
||||
}
|
||||
if (fp) {
|
||||
fp = GrXfermodeFragmentProcessor::Make(std::move(fp), nullptr, SkBlendMode::kModulate);
|
||||
@ -534,8 +564,7 @@ void draw_tiled_bitmap(GrRecordingContext* context,
|
||||
const SkPaint& paint,
|
||||
GrAA aa,
|
||||
SkCanvas::SrcRectConstraint constraint,
|
||||
GrSamplerState::WrapMode wm,
|
||||
GrSamplerState::Filter fm,
|
||||
GrSamplerState sampler,
|
||||
bool doBicubic) {
|
||||
SkRect clippedSrcRect = SkRect::Make(clippedSrcIRect);
|
||||
|
||||
@ -562,7 +591,7 @@ void draw_tiled_bitmap(GrRecordingContext* context,
|
||||
SkIntToScalar(iTileR.fTop));
|
||||
SkRect rectToDraw = tileR;
|
||||
srcToDst.mapRect(&rectToDraw);
|
||||
if (fm != GrSamplerState::Filter::kNearest || doBicubic) {
|
||||
if (sampler.filter() != GrSamplerState::Filter::kNearest || doBicubic) {
|
||||
SkIRect iClampRect;
|
||||
|
||||
if (SkCanvas::kFast_SrcRectConstraint == constraint) {
|
||||
@ -611,10 +640,9 @@ void draw_tiled_bitmap(GrRecordingContext* context,
|
||||
tileR.offset(-offset.fX, -offset.fY);
|
||||
SkMatrix offsetSrcToDst = srcToDst;
|
||||
offsetSrcToDst.preTranslate(offset.fX, offset.fY);
|
||||
|
||||
draw_texture_producer(context, rtc, clip, matrixProvider, paint, &tileProducer,
|
||||
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());
|
||||
const SkMatrix& ctm(matrixProvider.localToDevice());
|
||||
|
||||
bool doBicubic;
|
||||
GrSamplerState::Filter fm = GrSkFilterQualityToGrFilterMode(
|
||||
image->width(), image->height(), paint.getFilterQuality(), ctm, srcToDst,
|
||||
fContext->priv().options().fSharpenMipmappedTextures, &doBicubic);
|
||||
bool sharpenMM = fContext->priv().options().fSharpenMipmappedTextures;
|
||||
auto [fm, mm, bicubic] = GrInterpretFilterQuality(image->dimensions(), paint.getFilterQuality(),
|
||||
ctm, srcToDst, sharpenMM);
|
||||
|
||||
auto clip = this->clip();
|
||||
|
||||
@ -667,7 +694,7 @@ void SkGpuDevice::drawImageQuad(const SkImage* image, const SkRect* srcRect, con
|
||||
GrYUVAImageTextureMaker maker(fContext.get(), image);
|
||||
draw_texture_producer(fContext.get(), fRenderTargetContext.get(), clip, matrixProvider,
|
||||
paint, &maker, src, dst, dstClip, srcToDst, aa, aaFlags, constraint,
|
||||
wrapMode, fm, doBicubic);
|
||||
{wrapMode, fm, mm}, bicubic);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -691,7 +718,7 @@ void SkGpuDevice::drawImageQuad(const SkImage* image, const SkRect* srcRect, con
|
||||
GrTextureAdjuster adjuster(fContext.get(), std::move(view), colorInfo, pinnedUniqueID);
|
||||
draw_texture_producer(fContext.get(), fRenderTargetContext.get(), clip, matrixProvider,
|
||||
paint, &adjuster, src, dst, dstClip, srcToDst, aa, aaFlags,
|
||||
constraint, wrapMode, fm, doBicubic);
|
||||
constraint, {wrapMode, fm, mm}, bicubic);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -701,7 +728,7 @@ void SkGpuDevice::drawImageQuad(const SkImage* image, const SkRect* srcRect, con
|
||||
SkASSERT(!image->isTextureBacked());
|
||||
|
||||
int tileFilterPad;
|
||||
if (doBicubic) {
|
||||
if (bicubic) {
|
||||
tileFilterPad = GrBicubicEffect::kFilterTexelPad;
|
||||
} else if (GrSamplerState::Filter::kNearest == fm) {
|
||||
tileFilterPad = 0;
|
||||
@ -724,7 +751,7 @@ void SkGpuDevice::drawImageQuad(const SkImage* image, const SkRect* srcRect, con
|
||||
LogDrawScaleFactor(ctm, srcToDst, paint.getFilterQuality());
|
||||
draw_tiled_bitmap(fContext.get(), fRenderTargetContext.get(), clip, bm, tileSize,
|
||||
matrixProvider, srcToDst, src, clippedSubset, paint, aa,
|
||||
constraint, wrapMode, fm, doBicubic);
|
||||
constraint, {wrapMode, fm, mm}, bicubic);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -740,7 +767,7 @@ void SkGpuDevice::drawImageQuad(const SkImage* image, const SkRect* srcRect, con
|
||||
GrImageTextureMaker maker(fContext.get(), image, GrImageTexGenPolicy::kDraw);
|
||||
draw_texture_producer(fContext.get(), fRenderTargetContext.get(), clip, matrixProvider,
|
||||
paint, &maker, src, dst, dstClip, srcToDst, aa, aaFlags, constraint,
|
||||
wrapMode, fm, doBicubic);
|
||||
{wrapMode, fm, mm}, bicubic);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -749,7 +776,7 @@ void SkGpuDevice::drawImageQuad(const SkImage* image, const SkRect* srcRect, con
|
||||
GrBitmapTextureMaker maker(fContext.get(), bm, GrImageTexGenPolicy::kDraw);
|
||||
draw_texture_producer(fContext.get(), fRenderTargetContext.get(), clip, matrixProvider,
|
||||
paint, &maker, src, dst, dstClip, srcToDst, aa, aaFlags, constraint,
|
||||
wrapMode, fm, doBicubic);
|
||||
{wrapMode, fm, mm}, bicubic);
|
||||
}
|
||||
|
||||
// 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(
|
||||
set[base].fImage->colorSpace(), set[base].fImage->alphaType(),
|
||||
fRenderTargetContext->colorInfo().colorSpace(), kPremul_SkAlphaType);
|
||||
fRenderTargetContext->drawTextureSet(this->clip(), textures.get() + base, n, p,
|
||||
filter, mode, GrAA::kYes, constraint,
|
||||
this->localToDevice(), std::move(textureXform));
|
||||
fRenderTargetContext->drawTextureSet(this->clip(),
|
||||
textures.get() + base,
|
||||
n,
|
||||
p,
|
||||
filter,
|
||||
GrSamplerState::MipmapMode::kNone,
|
||||
mode,
|
||||
GrAA::kYes,
|
||||
constraint,
|
||||
this->localToDevice(),
|
||||
std::move(textureXform));
|
||||
}
|
||||
base = nextBase;
|
||||
n = 0;
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "src/core/SkColorSpacePriv.h"
|
||||
#include "src/core/SkImagePriv.h"
|
||||
#include "src/core/SkMaskFilterBase.h"
|
||||
#include "src/core/SkMatrixPriv.h"
|
||||
#include "src/core/SkMessageBus.h"
|
||||
#include "src/core/SkMipmap.h"
|
||||
#include "src/core/SkPaintPriv.h"
|
||||
@ -37,6 +38,7 @@
|
||||
#include "src/gpu/GrRecordingContextPriv.h"
|
||||
#include "src/gpu/GrTextureProxy.h"
|
||||
#include "src/gpu/GrXferProcessor.h"
|
||||
#include "src/gpu/SkGr.h"
|
||||
#include "src/gpu/effects/GrBicubicEffect.h"
|
||||
#include "src/gpu/effects/GrPorterDuffXferProcessor.h"
|
||||
#include "src/gpu/effects/GrXfermodeFragmentProcessor.h"
|
||||
@ -432,21 +434,25 @@ bool SkPaintToGrPaintWithTexture(GrRecordingContext* context,
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrSamplerState::Filter GrSkFilterQualityToGrFilterMode(int imageWidth, int imageHeight,
|
||||
SkFilterQuality paintFilterQuality,
|
||||
const SkMatrix& viewM,
|
||||
const SkMatrix& localM,
|
||||
bool sharpenMipmappedTextures,
|
||||
bool* doBicubic) {
|
||||
*doBicubic = false;
|
||||
if (imageWidth <= 1 && imageHeight <= 1) {
|
||||
return GrSamplerState::Filter::kNearest;
|
||||
std::tuple<GrSamplerState::Filter,
|
||||
GrSamplerState::MipmapMode,
|
||||
bool /*bicubic*/>
|
||||
GrInterpretFilterQuality(SkISize imageDims,
|
||||
SkFilterQuality paintFilterQuality,
|
||||
const SkMatrix& viewM,
|
||||
const SkMatrix& localM,
|
||||
bool sharpenMipmappedTextures) {
|
||||
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) {
|
||||
case kNone_SkFilterQuality:
|
||||
return GrSamplerState::Filter::kNearest;
|
||||
return {Filter::kNearest, MipmapMode::kNone, false};
|
||||
case kLow_SkFilterQuality:
|
||||
return GrSamplerState::Filter::kLinear;
|
||||
return {Filter::kLinear, MipmapMode::kNone, false};
|
||||
case kMedium_SkFilterQuality: {
|
||||
SkMatrix matrix;
|
||||
matrix.setConcat(viewM, localM);
|
||||
@ -460,18 +466,21 @@ GrSamplerState::Filter GrSkFilterQualityToGrFilterMode(int imageWidth, int image
|
||||
// 2^0.5/2 = s
|
||||
SkScalar mipScale = sharpenMipmappedTextures ? SK_ScalarRoot2Over2 : SK_Scalar1;
|
||||
if (matrix.getMinScale() < mipScale) {
|
||||
return GrSamplerState::Filter::kMipMap;
|
||||
return {Filter::kLinear, MipmapMode::kLinear, false};
|
||||
} else {
|
||||
// Don't trigger MIP level generation unnecessarily.
|
||||
return GrSamplerState::Filter::kLinear;
|
||||
return {Filter::kLinear, MipmapMode::kNone, false};
|
||||
}
|
||||
}
|
||||
case kHigh_SkFilterQuality: {
|
||||
SkMatrix matrix;
|
||||
matrix.setConcat(viewM, localM);
|
||||
GrSamplerState::Filter textureFilterMode;
|
||||
*doBicubic = GrBicubicEffect::ShouldUseBicubic(matrix, &textureFilterMode);
|
||||
return textureFilterMode;
|
||||
switch (SkMatrixPriv::AdjustHighQualityFilterLevel(matrix)) {
|
||||
case kNone_SkFilterQuality: return {Filter::kNearest, MipmapMode::kNone , false};
|
||||
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;
|
||||
|
@ -141,12 +141,19 @@ bool SkPaintToGrPaintWithTexture(GrRecordingContext*,
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Misc Sk to Gr type conversions
|
||||
|
||||
GrSamplerState::Filter GrSkFilterQualityToGrFilterMode(int imageWidth, int imageHeight,
|
||||
SkFilterQuality paintFilterQuality,
|
||||
const SkMatrix& viewM,
|
||||
const SkMatrix& localM,
|
||||
bool sharpenMipmappedTextures,
|
||||
bool* doBicubic);
|
||||
/**
|
||||
* Determines how to interpret SkFilterQuality given draw params and canvas state. If the returned
|
||||
* bool is true then bicubic filtering should be used (and the two other return values can be
|
||||
* ignored).
|
||||
*/
|
||||
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.");
|
||||
}
|
||||
|
||||
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(
|
||||
const GrSamplerState& params) {
|
||||
uint32_t key = params.asIndex();
|
||||
@ -136,17 +154,7 @@ D3D12_CPU_DESCRIPTOR_HANDLE GrD3DResourceProvider::findOrCreateCompatibleSampler
|
||||
return *samplerPtr;
|
||||
}
|
||||
|
||||
static D3D12_FILTER d3dFilterModes[] = {
|
||||
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_FILTER filter = d3d_filter(params);
|
||||
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());
|
||||
|
||||
|
@ -73,7 +73,6 @@ static wgpu::FilterMode to_dawn_filter_mode(GrSamplerState::Filter filter) {
|
||||
case GrSamplerState::Filter::kNearest:
|
||||
return wgpu::FilterMode::Nearest;
|
||||
case GrSamplerState::Filter::kLinear:
|
||||
case GrSamplerState::Filter::kMipMap:
|
||||
return wgpu::FilterMode::Linear;
|
||||
default:
|
||||
SkASSERT(!"unsupported filter mode");
|
||||
|
@ -329,25 +329,3 @@ std::unique_ptr<GrFragmentProcessor> GrBicubicEffect::TestCreate(GrProcessorTest
|
||||
}
|
||||
}
|
||||
#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,
|
||||
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:
|
||||
class Impl;
|
||||
|
||||
|
@ -15,8 +15,9 @@
|
||||
#include "src/sksl/SkSLCPP.h"
|
||||
#include "src/sksl/SkSLUtil.h"
|
||||
|
||||
using Mode = GrSamplerState::WrapMode;
|
||||
using Wrap = GrSamplerState::WrapMode;
|
||||
using Filter = GrSamplerState::Filter;
|
||||
using MipmapMode = GrSamplerState::MipmapMode;
|
||||
|
||||
struct GrTextureEffect::Sampling {
|
||||
GrSamplerState fHWSampler;
|
||||
@ -24,9 +25,9 @@ struct GrTextureEffect::Sampling {
|
||||
SkRect fShaderSubset = {0, 0, 0, 0};
|
||||
SkRect fShaderClamp = {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,
|
||||
GrSamplerState sampler,
|
||||
GrSamplerState wrap,
|
||||
const SkRect&,
|
||||
const SkRect*,
|
||||
const float border[4],
|
||||
@ -59,28 +60,29 @@ GrTextureEffect::Sampling::Sampling(const GrSurfaceProxy& proxy,
|
||||
ShaderMode fShaderMode;
|
||||
Span fShaderSubset;
|
||||
Span fShaderClamp;
|
||||
Mode fHWMode;
|
||||
Wrap fHWWrap;
|
||||
};
|
||||
|
||||
auto type = proxy.asTextureProxy()->textureType();
|
||||
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;
|
||||
bool canDoModeInHW = true;
|
||||
// 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])) {
|
||||
canDoModeInHW = false;
|
||||
} else if (mode != Mode::kClamp && !caps.npotTextureTileSupport() && !SkIsPow2(size)) {
|
||||
} else if (wrap != Wrap::kClamp && !caps.npotTextureTileSupport() && !SkIsPow2(size)) {
|
||||
canDoModeInHW = false;
|
||||
} else if (type != GrTextureType::k2D &&
|
||||
!(mode == Mode::kClamp || mode == Mode::kClampToBorder)) {
|
||||
!(wrap == Wrap::kClamp || wrap == Wrap::kClampToBorder)) {
|
||||
canDoModeInHW = false;
|
||||
}
|
||||
if (canDoModeInHW && size > 0 && subset.fA <= 0 && subset.fB >= size) {
|
||||
r.fShaderMode = ShaderMode::kNone;
|
||||
r.fHWMode = mode;
|
||||
r.fHWWrap = wrap;
|
||||
r.fShaderSubset = r.fShaderClamp = {0, 0};
|
||||
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
|
||||
// supported.
|
||||
r.fShaderMode = ShaderMode::kNone;
|
||||
r.fHWMode = Mode::kClamp;
|
||||
r.fHWWrap = Wrap::kClamp;
|
||||
r.fShaderSubset = r.fShaderClamp = {0, 0};
|
||||
return r;
|
||||
}
|
||||
r.fShaderMode = GetShaderMode(mode, filter);
|
||||
r.fHWMode = Mode::kClamp;
|
||||
r.fShaderMode = GetShaderMode(wrap, filter, mm);
|
||||
r.fHWWrap = Wrap::kClamp;
|
||||
return r;
|
||||
};
|
||||
|
||||
@ -128,7 +130,7 @@ GrTextureEffect::Sampling::Sampling(const GrSurfaceProxy& proxy,
|
||||
: Span{SK_FloatNegativeInfinity, SK_FloatInfinity};
|
||||
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[1] = y.fShaderMode;
|
||||
fShaderSubset = {x.fShaderSubset.fA, y.fShaderSubset.fA,
|
||||
@ -139,8 +141,8 @@ GrTextureEffect::Sampling::Sampling(const GrSurfaceProxy& proxy,
|
||||
}
|
||||
|
||||
bool GrTextureEffect::Sampling::hasBorderAlpha() const {
|
||||
if (fHWSampler.wrapModeX() == GrSamplerState::WrapMode::kClampToBorder ||
|
||||
fHWSampler.wrapModeY() == GrSamplerState::WrapMode::kClampToBorder) {
|
||||
if (fHWSampler.wrapModeX() == Wrap::kClampToBorder ||
|
||||
fHWSampler.wrapModeY() == Wrap::kClampToBorder) {
|
||||
return true;
|
||||
}
|
||||
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,
|
||||
SkAlphaType alphaType,
|
||||
const SkMatrix& matrix,
|
||||
Filter filter) {
|
||||
Filter filter,
|
||||
MipmapMode mm) {
|
||||
SkMatrix final;
|
||||
bool lazyProxyNormalization;
|
||||
get_matrix(matrix, view, &final, &lazyProxyNormalization);
|
||||
return GrMatrixEffect::Make(final, std::unique_ptr<GrFragmentProcessor>(
|
||||
new GrTextureEffect(std::move(view),
|
||||
alphaType,
|
||||
Sampling(filter),
|
||||
Sampling(filter, mm),
|
||||
lazyProxyNormalization)));
|
||||
}
|
||||
|
||||
@ -262,14 +265,14 @@ std::unique_ptr<GrFragmentProcessor> GrTextureEffect::MakeCustomLinearFilterInse
|
||||
GrSurfaceProxyView view,
|
||||
SkAlphaType alphaType,
|
||||
const SkMatrix& matrix,
|
||||
GrSamplerState::WrapMode wx,
|
||||
GrSamplerState::WrapMode wy,
|
||||
Wrap wx,
|
||||
Wrap wy,
|
||||
const SkRect& subset,
|
||||
const SkRect* domain,
|
||||
SkVector inset,
|
||||
const GrCaps& caps,
|
||||
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);
|
||||
SkMatrix final;
|
||||
bool lazyProxyNormalization;
|
||||
@ -279,32 +282,39 @@ std::unique_ptr<GrFragmentProcessor> GrTextureEffect::MakeCustomLinearFilterInse
|
||||
std::move(view), alphaType, sampling, lazyProxyNormalization)));
|
||||
}
|
||||
|
||||
GrTextureEffect::ShaderMode GrTextureEffect::GetShaderMode(GrSamplerState::WrapMode mode,
|
||||
GrSamplerState::Filter filter) {
|
||||
switch (mode) {
|
||||
case GrSamplerState::WrapMode::kMirrorRepeat:
|
||||
GrTextureEffect::ShaderMode GrTextureEffect::GetShaderMode(Wrap wrap,
|
||||
Filter filter,
|
||||
MipmapMode mm) {
|
||||
switch (wrap) {
|
||||
case Wrap::kMirrorRepeat:
|
||||
return ShaderMode::kMirrorRepeat;
|
||||
case GrSamplerState::WrapMode::kClamp:
|
||||
case Wrap::kClamp:
|
||||
return ShaderMode::kClamp;
|
||||
case GrSamplerState::WrapMode::kRepeat:
|
||||
switch (filter) {
|
||||
case GrSamplerState::Filter::kNearest:
|
||||
return ShaderMode::kRepeatNearest;
|
||||
case GrSamplerState::Filter::kLinear:
|
||||
return ShaderMode::kRepeatLinear;
|
||||
case GrSamplerState::Filter::kMipMap:
|
||||
return ShaderMode::kRepeatMipMap;
|
||||
case Wrap::kRepeat:
|
||||
switch (mm) {
|
||||
case MipmapMode::kNone:
|
||||
switch (filter) {
|
||||
case Filter::kNearest: return ShaderMode::kRepeat_Nearest_None;
|
||||
case Filter::kLinear: return ShaderMode::kRepeat_Linear_None;
|
||||
}
|
||||
SkUNREACHABLE;
|
||||
case MipmapMode::kLinear:
|
||||
switch (filter) {
|
||||
case Filter::kNearest: return ShaderMode::kRepeat_Nearest_Mipmap;
|
||||
case Filter::kLinear: return ShaderMode::kRepeat_Linear_Mipmap;
|
||||
}
|
||||
SkUNREACHABLE;
|
||||
}
|
||||
SkUNREACHABLE;
|
||||
case GrSamplerState::WrapMode::kClampToBorder:
|
||||
return filter == GrSamplerState::Filter::kNearest ? ShaderMode::kClampToBorderNearest
|
||||
: ShaderMode::kClampToBorderFilter;
|
||||
case Wrap::kClampToBorder:
|
||||
return filter == Filter::kNearest ? ShaderMode::kClampToBorder_Nearest
|
||||
: ShaderMode::kClampToBorder_Filter;
|
||||
}
|
||||
SkUNREACHABLE;
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -366,12 +376,13 @@ void GrTextureEffect::Impl::emitCode(EmitArgs& args) {
|
||||
switch (m) {
|
||||
case ShaderMode::kNone: return false;
|
||||
case ShaderMode::kClamp: return false;
|
||||
case ShaderMode::kRepeatNearest: return true;
|
||||
case ShaderMode::kRepeatLinear: return true;
|
||||
case ShaderMode::kRepeatMipMap: return true;
|
||||
case ShaderMode::kRepeat_Nearest_None: return true;
|
||||
case ShaderMode::kRepeat_Linear_None: return true;
|
||||
case ShaderMode::kRepeat_Nearest_Mipmap: return true;
|
||||
case ShaderMode::kRepeat_Linear_Mipmap: return true;
|
||||
case ShaderMode::kMirrorRepeat: return true;
|
||||
case ShaderMode::kClampToBorderNearest: return true;
|
||||
case ShaderMode::kClampToBorderFilter: return true;
|
||||
case ShaderMode::kClampToBorder_Nearest: return true;
|
||||
case ShaderMode::kClampToBorder_Filter: return true;
|
||||
}
|
||||
SkUNREACHABLE;
|
||||
};
|
||||
@ -380,12 +391,13 @@ void GrTextureEffect::Impl::emitCode(EmitArgs& args) {
|
||||
switch (m) {
|
||||
case ShaderMode::kNone: return false;
|
||||
case ShaderMode::kClamp: return true;
|
||||
case ShaderMode::kRepeatNearest: return true;
|
||||
case ShaderMode::kRepeatLinear: return true;
|
||||
case ShaderMode::kRepeatMipMap: return true;
|
||||
case ShaderMode::kRepeat_Nearest_None: return true;
|
||||
case ShaderMode::kRepeat_Linear_None: return true;
|
||||
case ShaderMode::kRepeat_Nearest_Mipmap: return true;
|
||||
case ShaderMode::kRepeat_Linear_Mipmap: return true;
|
||||
case ShaderMode::kMirrorRepeat: return true;
|
||||
case ShaderMode::kClampToBorderNearest: return false;
|
||||
case ShaderMode::kClampToBorderFilter: return true;
|
||||
case ShaderMode::kClampToBorder_Nearest: return false;
|
||||
case ShaderMode::kClampToBorder_Filter: return true;
|
||||
}
|
||||
SkUNREACHABLE;
|
||||
};
|
||||
@ -397,12 +409,13 @@ void GrTextureEffect::Impl::emitCode(EmitArgs& args) {
|
||||
switch (m) {
|
||||
case ShaderMode::kNone: return false;
|
||||
case ShaderMode::kClamp: return false;
|
||||
case ShaderMode::kRepeatNearest: return false;
|
||||
case ShaderMode::kRepeatLinear: return true;
|
||||
case ShaderMode::kRepeatMipMap: return true;
|
||||
case ShaderMode::kRepeat_Nearest_None: return false;
|
||||
case ShaderMode::kRepeat_Linear_None: return true;
|
||||
case ShaderMode::kRepeat_Nearest_Mipmap: return true;
|
||||
case ShaderMode::kRepeat_Linear_Mipmap: return true;
|
||||
case ShaderMode::kMirrorRepeat: return false;
|
||||
case ShaderMode::kClampToBorderNearest: return true;
|
||||
case ShaderMode::kClampToBorderFilter: return true;
|
||||
case ShaderMode::kClampToBorder_Nearest: return true;
|
||||
case ShaderMode::kClampToBorder_Filter: return true;
|
||||
}
|
||||
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
|
||||
// coords to be within the subset.
|
||||
case ShaderMode::kNone:
|
||||
case ShaderMode::kClampToBorderNearest:
|
||||
case ShaderMode::kClampToBorderFilter:
|
||||
case ShaderMode::kClampToBorder_Nearest:
|
||||
case ShaderMode::kClampToBorder_Filter:
|
||||
case ShaderMode::kClamp:
|
||||
fb->codeAppendf("subsetCoord.%s = inCoord.%s;", coordSwizzle, coordSwizzle);
|
||||
break;
|
||||
case ShaderMode::kRepeatNearest:
|
||||
case ShaderMode::kRepeatLinear:
|
||||
case ShaderMode::kRepeat_Nearest_None:
|
||||
case ShaderMode::kRepeat_Linear_None:
|
||||
fb->codeAppendf(
|
||||
"subsetCoord.%s = mod(inCoord.%s - %s.%s, %s.%s - %s.%s) + "
|
||||
"%s.%s;",
|
||||
@ -472,7 +485,8 @@ void GrTextureEffect::Impl::emitCode(EmitArgs& args) {
|
||||
subsetStopSwizzle, subsetName, subsetStartSwizzle, subsetName,
|
||||
subsetStartSwizzle);
|
||||
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
|
||||
// are both "moving" at the same speed (if not direction) as
|
||||
// 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* repeatCoordWeightX = nullptr;
|
||||
const char* extraRepeatCoordY = 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;");
|
||||
extraRepeatCoordX = "extraRepeatCoordX";
|
||||
repeatCoordWeightX = "repeatCoordWeightX";
|
||||
}
|
||||
if (m[1] == ShaderMode::kRepeatMipMap) {
|
||||
if (mipmapRepeatY) {
|
||||
fb->codeAppend("float extraRepeatCoordY; half repeatCoordWeightY;");
|
||||
extraRepeatCoordY = "extraRepeatCoordY";
|
||||
repeatCoordWeightY = "repeatCoordWeightY";
|
||||
@ -557,20 +577,20 @@ void GrTextureEffect::Impl::emitCode(EmitArgs& args) {
|
||||
clampCoord(useClamp[0], "x", "x", "z");
|
||||
clampCoord(useClamp[1], "y", "y", "w");
|
||||
|
||||
// Additional clamping for the extra coords for kRepeatMipMap.
|
||||
if (m[0] == ShaderMode::kRepeatMipMap) {
|
||||
// Additional clamping for the extra coords for kRepeat with mip maps.
|
||||
if (mipmapRepeatX) {
|
||||
fb->codeAppendf("extraRepeatCoordX = clamp(extraRepeatCoordX, %s.x, %s.z);", clampName,
|
||||
clampName);
|
||||
}
|
||||
if (m[1] == ShaderMode::kRepeatMipMap) {
|
||||
if (mipmapRepeatY) {
|
||||
fb->codeAppendf("extraRepeatCoordY = clamp(extraRepeatCoordY, %s.y, %s.w);", clampName,
|
||||
clampName);
|
||||
}
|
||||
|
||||
// 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.
|
||||
if (m[0] == ShaderMode::kRepeatMipMap && m[1] == ShaderMode::kRepeatMipMap) {
|
||||
if (mipmapRepeatX && mipmapRepeatY) {
|
||||
fb->codeAppendf(
|
||||
"half4 textureColor ="
|
||||
" mix(mix(%s, %s, repeatCoordWeightX),"
|
||||
@ -581,11 +601,11 @@ void GrTextureEffect::Impl::emitCode(EmitArgs& args) {
|
||||
read("float2(clampedCoord.x, 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);",
|
||||
read("clampedCoord").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);",
|
||||
read("clampedCoord").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
|
||||
// to implement shader-based filtering for kClampToBorder and kRepeat.
|
||||
|
||||
if (m[0] == ShaderMode::kRepeatLinear || m[0] == ShaderMode::kClampToBorderFilter) {
|
||||
bool repeatLinearFilterX = m[0] == ShaderMode::kRepeat_Linear_None ||
|
||||
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);");
|
||||
if (m[0] == ShaderMode::kRepeatLinear) {
|
||||
if (repeatLinearFilterX) {
|
||||
fb->codeAppendf("float repeatCoordX = errX > 0 ? %s.x : %s.z;",
|
||||
clampName, clampName);
|
||||
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);");
|
||||
if (m[1] == ShaderMode::kRepeatLinear) {
|
||||
if (repeatLinearFilterY) {
|
||||
fb->codeAppendf("float repeatCoordY = errY > 0 ? %s.y : %s.w;",
|
||||
clampName, clampName);
|
||||
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
|
||||
// or a corner. Then blend the multiple reads using the err values calculated
|
||||
// above.
|
||||
const char* ifStr = "if";
|
||||
if (m[0] == ShaderMode::kRepeatLinear && m[1] == ShaderMode::kRepeatLinear) {
|
||||
if (repeatLinearFilterX && repeatLinearFilterY) {
|
||||
auto repeatLinearReadXY = read("float2(repeatCoordX, repeatCoordY)");
|
||||
fb->codeAppendf(
|
||||
"if (errX != 0 && errY != 0) {"
|
||||
@ -635,14 +658,14 @@ void GrTextureEffect::Impl::emitCode(EmitArgs& args) {
|
||||
repeatLinearReadXY.c_str());
|
||||
ifStr = "else if";
|
||||
}
|
||||
if (m[0] == ShaderMode::kRepeatLinear) {
|
||||
if (repeatLinearFilterX) {
|
||||
fb->codeAppendf(
|
||||
"%s (errX != 0) {"
|
||||
" textureColor = mix(textureColor, %s, abs(errX));"
|
||||
"}",
|
||||
ifStr, repeatLinearReadX.c_str());
|
||||
}
|
||||
if (m[1] == ShaderMode::kRepeatLinear) {
|
||||
if (repeatLinearFilterY) {
|
||||
fb->codeAppendf(
|
||||
"%s (errY != 0) {"
|
||||
" 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
|
||||
// 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);
|
||||
}
|
||||
if (m[1] == ShaderMode::kClampToBorderFilter) {
|
||||
if (m[1] == ShaderMode::kClampToBorder_Filter) {
|
||||
fb->codeAppendf("textureColor = mix(textureColor, %s, min(abs(errY), 1));", borderName);
|
||||
}
|
||||
|
||||
// Do hard-edge shader transition to border color for kClampToBorderNearest at the
|
||||
// subset boundaries. Snap the input coordinates to nearest neighbor (with an
|
||||
// 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(
|
||||
"float snappedX = floor(inCoord.x + 0.001) + 0.5;"
|
||||
"if (snappedX < %s.x || snappedX > %s.z) {"
|
||||
@ -670,7 +693,7 @@ void GrTextureEffect::Impl::emitCode(EmitArgs& args) {
|
||||
"}",
|
||||
subsetName, subsetName, borderName);
|
||||
}
|
||||
if (m[1] == ShaderMode::kClampToBorderNearest) {
|
||||
if (m[1] == ShaderMode::kClampToBorder_Nearest) {
|
||||
fb->codeAppendf(
|
||||
"float snappedY = floor(inCoord.y + 0.001) + 0.5;"
|
||||
"if (snappedY < %s.y || snappedY > %s.w) {"
|
||||
@ -796,26 +819,15 @@ GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrTextureEffect);
|
||||
#if GR_TEST_UTILS
|
||||
std::unique_ptr<GrFragmentProcessor> GrTextureEffect::TestCreate(GrProcessorTestData* testData) {
|
||||
auto [view, ct, at] = testData->randomView();
|
||||
Mode wrapModes[2];
|
||||
Wrap wrapModes[2];
|
||||
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) {
|
||||
switch (testData->fRandom->nextULessThan(3)) {
|
||||
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;
|
||||
mm = testData->fRandom->nextBool() ? MipmapMode::kLinear : MipmapMode::kNone;
|
||||
}
|
||||
GrSamplerState params(wrapModes, filter);
|
||||
GrSamplerState params(wrapModes, filter, mm);
|
||||
|
||||
const SkMatrix& matrix = GrTest::TestMatrix(testData->fRandom);
|
||||
return GrTextureEffect::Make(std::move(view), at, matrix, params, *testData->caps());
|
||||
|
@ -23,7 +23,8 @@ public:
|
||||
GrSurfaceProxyView,
|
||||
SkAlphaType,
|
||||
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.
|
||||
@ -124,16 +125,19 @@ private:
|
||||
* filter.
|
||||
*/
|
||||
enum class ShaderMode : uint16_t {
|
||||
kNone, // Using HW mode
|
||||
kClamp, // Shader based clamp, no filter specialization
|
||||
kRepeatNearest, // Simple repeat for nearest sampling
|
||||
kRepeatLinear, // Filter across the subset boundary for kRepeat mode
|
||||
kRepeatMipMap, // Logic for LOD selection with kRepeat mode.
|
||||
kMirrorRepeat, // Mirror repeat (doesn't depend on filter))
|
||||
kClampToBorderNearest, // Logic for hard transition to border color when not filtering.
|
||||
kClampToBorderFilter, // Logic for fading to border color when filtering.
|
||||
kNone, // Using HW mode
|
||||
kClamp, // Shader based clamp, no filter specialization
|
||||
kRepeat_Nearest_None, // Simple repeat for nearest sampling, no mipmapping
|
||||
kRepeat_Linear_None, // Filter the subset boundary for kRepeat mode, no mip mapping
|
||||
kRepeat_Linear_Mipmap, // Logic for linear filtering and LOD selection with kRepeat mode.
|
||||
kRepeat_Nearest_Mipmap, // Logic for nearest filtering and LOD selection with kRepeat mode.
|
||||
kMirrorRepeat, // Mirror repeat (doesn't depend on filter))
|
||||
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);
|
||||
|
||||
GrSurfaceProxyView fView;
|
||||
|
@ -116,7 +116,7 @@ std::unique_ptr<GrFragmentProcessor> GrYUVtoRGBEffect::Make(GrSurfaceProxyView v
|
||||
}
|
||||
}
|
||||
if (subset) {
|
||||
SkASSERT(samplerState.filter() != GrSamplerState::Filter::kMipMap);
|
||||
SkASSERT(samplerState.mipmapped() == GrMipmapped::kNo);
|
||||
if (makeLinearWithSnap) {
|
||||
// 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
|
||||
@ -137,7 +137,6 @@ std::unique_ptr<GrFragmentProcessor> GrYUVtoRGBEffect::Make(GrSurfaceProxyView v
|
||||
*planeMatrix, samplerState, planeSubset,
|
||||
planeDomain, caps, planeBorders[i]);
|
||||
} else {
|
||||
SkASSERT(samplerState.filter() != GrSamplerState::Filter::kMipMap);
|
||||
planeFPs[i] = GrTextureEffect::MakeSubset(views[i], kUnknown_SkAlphaType,
|
||||
*planeMatrix, samplerState, planeSubset,
|
||||
caps, planeBorders[i]);
|
||||
|
@ -178,18 +178,23 @@ static GrGLenum filter_to_gl_mag_filter(GrSamplerState::Filter filter) {
|
||||
switch (filter) {
|
||||
case GrSamplerState::Filter::kNearest: return GR_GL_NEAREST;
|
||||
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) {
|
||||
switch (filter) {
|
||||
case GrSamplerState::Filter::kNearest: return GR_GL_NEAREST;
|
||||
case GrSamplerState::Filter::kLinear: return GR_GL_LINEAR;
|
||||
case GrSamplerState::Filter::kMipMap: return GR_GL_LINEAR_MIPMAP_LINEAR;
|
||||
static GrGLenum filter_to_gl_min_filter(GrSamplerState::Filter filter,
|
||||
GrSamplerState::MipmapMode mm) {
|
||||
switch (mm) {
|
||||
case GrSamplerState::MipmapMode::kNone:
|
||||
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,
|
||||
@ -203,7 +208,7 @@ static inline GrGLenum wrap_mode_to_gl_wrap(GrSamplerState::WrapMode wrapMode,
|
||||
SkASSERT(caps.clampToBorderSupport());
|
||||
return GR_GL_CLAMP_TO_BORDER;
|
||||
}
|
||||
SK_ABORT("Unknown wrap mode");
|
||||
SkUNREACHABLE;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -240,10 +245,10 @@ public:
|
||||
return;
|
||||
}
|
||||
fSamplers[index] = s;
|
||||
auto minFilter = filter_to_gl_min_filter(state.filter());
|
||||
auto magFilter = filter_to_gl_mag_filter(state.filter());
|
||||
auto wrapX = wrap_mode_to_gl_wrap(state.wrapModeX(), fGpu->glCaps());
|
||||
auto wrapY = wrap_mode_to_gl_wrap(state.wrapModeY(), fGpu->glCaps());
|
||||
GrGLenum minFilter = filter_to_gl_min_filter(state.filter(), state.mipmapMode());
|
||||
GrGLenum magFilter = filter_to_gl_mag_filter(state.filter());
|
||||
GrGLenum wrapX = wrap_mode_to_gl_wrap(state.wrapModeX(), fGpu->glCaps());
|
||||
GrGLenum wrapY = wrap_mode_to_gl_wrap(state.wrapModeY(), fGpu->glCaps());
|
||||
GR_GL_CALL(fGpu->glInterface(),
|
||||
SamplerParameteri(s, GR_GL_TEXTURE_MIN_FILTER, minFilter));
|
||||
GR_GL_CALL(fGpu->glInterface(),
|
||||
@ -2574,37 +2579,32 @@ void GrGLGpu::bindTexture(int unitIdx, GrSamplerState samplerState, const GrSwiz
|
||||
fHWTextureUnitBindings[unitIdx].setBoundID(target, textureID);
|
||||
}
|
||||
|
||||
if (samplerState.filter() == GrSamplerState::Filter::kMipMap) {
|
||||
if (samplerState.mipmapped() == GrMipmapped::kYes) {
|
||||
if (!this->caps()->mipmapSupport() ||
|
||||
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();
|
||||
bool setAll = timestamp < fResetTimestampForTextureParameters;
|
||||
|
||||
const GrGLTextureParameters::SamplerOverriddenState* samplerStateToRecord = nullptr;
|
||||
GrGLTextureParameters::SamplerOverriddenState newSamplerState;
|
||||
if (fSamplerObjectCache) {
|
||||
fSamplerObjectCache->bindSampler(unitIdx, samplerState);
|
||||
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 =
|
||||
texture->parameters()->samplerOverriddenState();
|
||||
if (setAll || oldSamplerState.fMinFilter != GR_GL_LINEAR_MIPMAP_LINEAR) {
|
||||
if (setAll || oldSamplerState.fMinFilter != minFilter) {
|
||||
this->setTextureUnit(unitIdx);
|
||||
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MIN_FILTER,
|
||||
GR_GL_LINEAR_MIPMAP_LINEAR));
|
||||
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MIN_FILTER, minFilter));
|
||||
newSamplerState = oldSamplerState;
|
||||
newSamplerState.fMinFilter = GR_GL_LINEAR_MIPMAP_LINEAR;
|
||||
newSamplerState.fMinFilter = minFilter;
|
||||
samplerStateToRecord = &newSamplerState;
|
||||
}
|
||||
}
|
||||
@ -2614,7 +2614,8 @@ void GrGLGpu::bindTexture(int unitIdx, GrSamplerState samplerState, const GrSwiz
|
||||
texture->parameters()->samplerOverriddenState();
|
||||
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.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) {
|
||||
static MTLSamplerMinMagFilter mtlMinMagFilterModes[] = {
|
||||
MTLSamplerMinMagFilterNearest,
|
||||
MTLSamplerMinMagFilterLinear,
|
||||
MTLSamplerMinMagFilterLinear
|
||||
};
|
||||
MTLSamplerMinMagFilter minMagFilter = [&] {
|
||||
switch (samplerState.filter()) {
|
||||
case GrSamplerState::Filter::kNearest: return MTLSamplerMinMagFilterNearest;
|
||||
case GrSamplerState::Filter::kLinear: return MTLSamplerMinMagFilterLinear;
|
||||
}
|
||||
SkUNREACHABLE;
|
||||
}();
|
||||
|
||||
static_assert((int)GrSamplerState::Filter::kNearest == 0);
|
||||
static_assert((int)GrSamplerState::Filter::kLinear == 1);
|
||||
static_assert((int)GrSamplerState::Filter::kMipMap == 2);
|
||||
MTLSamplerMipFilter mipFilter = [&] {
|
||||
switch (samplerState.mipmapMode()) {
|
||||
case GrSamplerState::MipmapMode::kNone: return MTLSamplerMipFilterNotMipmapped;
|
||||
case GrSamplerState::MipmapMode::kLinear: return MTLSamplerMipFilterLinear;
|
||||
}
|
||||
SkUNREACHABLE;
|
||||
}();
|
||||
|
||||
auto samplerDesc = [[MTLSamplerDescriptor alloc] init];
|
||||
samplerDesc.rAddressMode = MTLSamplerAddressModeClampToEdge;
|
||||
@ -57,12 +63,11 @@ GrMtlSampler* GrMtlSampler::Create(const GrMtlGpu* gpu, GrSamplerState samplerSt
|
||||
gpu->mtlCaps());
|
||||
samplerDesc.tAddressMode = wrap_mode_to_mtl_sampler_address(samplerState.wrapModeY(),
|
||||
gpu->mtlCaps());
|
||||
samplerDesc.magFilter = mtlMinMagFilterModes[static_cast<int>(samplerState.filter())];
|
||||
samplerDesc.minFilter = mtlMinMagFilterModes[static_cast<int>(samplerState.filter())];
|
||||
samplerDesc.mipFilter = MTLSamplerMipFilterLinear;
|
||||
samplerDesc.magFilter = minMagFilter;
|
||||
samplerDesc.minFilter = minMagFilter;
|
||||
samplerDesc.mipFilter = mipFilter;
|
||||
samplerDesc.lodMinClamp = 0.0f;
|
||||
bool useMipMaps = GrSamplerState::Filter::kMipMap == samplerState.filter();
|
||||
samplerDesc.lodMaxClamp = !useMipMaps ? 0.0f : 10000.0f;
|
||||
samplerDesc.lodMaxClamp = FLT_MAX; // default value according to docs.
|
||||
samplerDesc.maxAnisotropy = 1.0f;
|
||||
samplerDesc.normalizedCoordinates = true;
|
||||
if (@available(macOS 10.11, iOS 9.0, *)) {
|
||||
|
@ -165,8 +165,7 @@ public:
|
||||
const char* name() const override { return "NonAALatticeOp"; }
|
||||
|
||||
void visitProxies(const VisitProxyFunc& func) const override {
|
||||
bool mipped = (GrSamplerState::Filter::kMipMap == fFilter);
|
||||
func(fView.proxy(), GrMipmapped(mipped));
|
||||
func(fView.proxy(), GrMipmapped::kNo);
|
||||
if (fProgramInfo) {
|
||||
fProgramInfo->visitFPProxies(func);
|
||||
} else {
|
||||
|
@ -58,11 +58,13 @@ static SkSize axis_aligned_quad_size(const GrQuad& quad) {
|
||||
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 (srcQuad.quadType() != GrQuad::Type::kAxisAligned ||
|
||||
dstQuad.quadType() != GrQuad::Type::kAxisAligned) {
|
||||
return true;
|
||||
return {true, true};
|
||||
}
|
||||
|
||||
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
|
||||
// identically).
|
||||
SkASSERT(srcRect.isSorted());
|
||||
return srcRect.width() != dstRect.width() || srcRect.height() != dstRect.height() ||
|
||||
SkScalarFraction(srcRect.fLeft) != SkScalarFraction(dstRect.fLeft) ||
|
||||
SkScalarFraction(srcRect.fTop) != SkScalarFraction(dstRect.fTop);
|
||||
} else {
|
||||
// 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.
|
||||
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;
|
||||
}
|
||||
bool filter = srcRect.width() != dstRect.width() || srcRect.height() != dstRect.height() ||
|
||||
SkScalarFraction(srcRect.fLeft) != SkScalarFraction(dstRect.fLeft) ||
|
||||
SkScalarFraction(srcRect.fTop) != SkScalarFraction(dstRect.fTop);
|
||||
bool mm = srcRect.width() > dstRect.width() || srcRect.height() > dstRect.height();
|
||||
return {filter, mm};
|
||||
}
|
||||
// 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
|
||||
@ -222,13 +226,14 @@ public:
|
||||
GrSurfaceProxyView proxyView,
|
||||
sk_sp<GrColorSpaceXform> textureXform,
|
||||
GrSamplerState::Filter filter,
|
||||
GrSamplerState::MipmapMode mm,
|
||||
const SkPMColor4f& color,
|
||||
GrTextureOp::Saturate saturate,
|
||||
GrAAType aaType,
|
||||
DrawQuad* quad,
|
||||
const SkRect* subset) {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -237,6 +242,7 @@ public:
|
||||
int cnt,
|
||||
int proxyRunCnt,
|
||||
GrSamplerState::Filter filter,
|
||||
GrSamplerState::MipmapMode mm,
|
||||
GrTextureOp::Saturate saturate,
|
||||
GrAAType aaType,
|
||||
SkCanvas::SrcRectConstraint constraint,
|
||||
@ -249,7 +255,7 @@ public:
|
||||
GrOpMemoryPool* pool = context->priv().opMemoryPool();
|
||||
void* mem = pool->allocate(size);
|
||||
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)));
|
||||
}
|
||||
|
||||
@ -262,7 +268,7 @@ public:
|
||||
const char* name() const override { return "TextureOp"; }
|
||||
|
||||
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) {
|
||||
func(fViewCountPairs[p].fProxy.get(), GrMipmapped(mipped));
|
||||
}
|
||||
@ -277,9 +283,10 @@ public:
|
||||
str.appendf("# draws: %d\n", fQuads.count());
|
||||
auto iter = fQuads.iterator();
|
||||
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(),
|
||||
static_cast<int>(fMetadata.fFilter));
|
||||
static_cast<int>(fMetadata.fFilter),
|
||||
static_cast<int>(fMetadata.fMipmapMode));
|
||||
int i = 0;
|
||||
while(i < fViewCountPairs[p].fQuadCnt && iter.next()) {
|
||||
const GrQuad* quad = iter.deviceQuad();
|
||||
@ -368,12 +375,16 @@ private:
|
||||
// performance (since texture ops are one of the most commonly used in an app).
|
||||
struct Metadata {
|
||||
// AAType must be filled after initialization; ColorType is determined in finalize()
|
||||
Metadata(const GrSwizzle& swizzle, GrSamplerState::Filter filter,
|
||||
GrQuadPerEdgeAA::Subset subset, GrTextureOp::Saturate saturate)
|
||||
Metadata(const GrSwizzle& swizzle,
|
||||
GrSamplerState::Filter filter,
|
||||
GrSamplerState::MipmapMode mm,
|
||||
GrQuadPerEdgeAA::Subset subset,
|
||||
GrTextureOp::Saturate saturate)
|
||||
: fSwizzle(swizzle)
|
||||
, fProxyCount(1)
|
||||
, fTotalQuadCount(1)
|
||||
, fFilter(static_cast<uint16_t>(filter))
|
||||
, fMipmapMode(static_cast<uint16_t>(mm))
|
||||
, fAAType(static_cast<uint16_t>(GrAAType::kNone))
|
||||
, fColorType(static_cast<uint16_t>(ColorType::kNone))
|
||||
, 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
|
||||
uint16_t fFilter : 2; // GrSamplerState::Filter
|
||||
uint16_t fMipmapMode : 2; // GrSamplerState::MipmapMode
|
||||
uint16_t fAAType : 2; // GrAAType
|
||||
uint16_t fColorType : 2; // GrQuadPerEdgeAA::ColorType
|
||||
uint16_t fSubset : 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 {
|
||||
return static_cast<GrSamplerState::Filter>(fFilter);
|
||||
}
|
||||
GrSamplerState::MipmapMode mipmapMode() const {
|
||||
return static_cast<GrSamplerState::MipmapMode>(fMipmapMode);
|
||||
}
|
||||
GrAAType aaType() const { return static_cast<GrAAType>(fAAType); }
|
||||
ColorType colorType() const { return static_cast<ColorType>(fColorType); }
|
||||
Subset subset() const { return static_cast<Subset>(fSubset); }
|
||||
@ -449,6 +464,7 @@ private:
|
||||
TextureOp(GrSurfaceProxyView proxyView,
|
||||
sk_sp<GrColorSpaceXform> textureColorSpaceXform,
|
||||
GrSamplerState::Filter filter,
|
||||
GrSamplerState::MipmapMode mm,
|
||||
const SkPMColor4f& color,
|
||||
GrTextureOp::Saturate saturate,
|
||||
GrAAType aaType,
|
||||
@ -458,8 +474,7 @@ private:
|
||||
, fQuads(1, true /* includes locals */)
|
||||
, fTextureColorSpaceXform(std::move(textureColorSpaceXform))
|
||||
, 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
|
||||
// optimizations based on the rect and matrix when appropriate
|
||||
GrQuadUtils::ResolveAAType(aaType, quad->fEdgeFlags, quad->fDevice,
|
||||
@ -498,6 +513,7 @@ private:
|
||||
int cnt,
|
||||
int proxyRunCnt,
|
||||
GrSamplerState::Filter filter,
|
||||
GrSamplerState::MipmapMode mm,
|
||||
GrTextureOp::Saturate saturate,
|
||||
GrAAType aaType,
|
||||
SkCanvas::SrcRectConstraint constraint,
|
||||
@ -507,8 +523,11 @@ private:
|
||||
, fQuads(cnt, true /* includes locals */)
|
||||
, fTextureColorSpaceXform(std::move(textureColorSpaceXform))
|
||||
, fDesc(nullptr)
|
||||
, fMetadata(set[0].fProxyView.swizzle(), GrSamplerState::Filter::kNearest,
|
||||
Subset::kNo, saturate) {
|
||||
, fMetadata(set[0].fProxyView.swizzle(),
|
||||
GrSamplerState::Filter::kNearest,
|
||||
GrSamplerState::MipmapMode::kNone,
|
||||
Subset::kNo,
|
||||
saturate) {
|
||||
// Update counts to reflect the batch op
|
||||
fMetadata.fProxyCount = SkToUInt(proxyRunCnt);
|
||||
fMetadata.fTotalQuadCount = SkToUInt(cnt);
|
||||
@ -518,6 +537,7 @@ private:
|
||||
GrAAType netAAType = GrAAType::kNone; // aa type maximally compatible with all dst rects
|
||||
Subset netSubset = Subset::kNo;
|
||||
GrSamplerState::Filter netFilter = GrSamplerState::Filter::kNearest;
|
||||
GrSamplerState::MipmapMode netMM = GrSamplerState::MipmapMode::kNone;
|
||||
|
||||
const GrSurfaceProxy* curProxy = nullptr;
|
||||
|
||||
@ -525,6 +545,9 @@ private:
|
||||
// increases when set[q]'s proxy changes.
|
||||
int p = 0;
|
||||
for (int q = 0; q < cnt; ++q) {
|
||||
SkASSERT(mm == GrSamplerState::MipmapMode::kNone ||
|
||||
(set[0].fProxyView.proxy()->asTextureProxy()->mipmapped() ==
|
||||
GrMipmapped::kYes));
|
||||
if (q == 0) {
|
||||
// We do not placement new the first ViewCountPair since that one is allocated and
|
||||
// initialized as part of the GrTextureOp creation.
|
||||
@ -561,13 +584,19 @@ private:
|
||||
quad.fLocal = GrQuad(set[q].fSrcRect);
|
||||
}
|
||||
|
||||
if (netFilter != filter && filter_has_effect(quad.fLocal, quad.fDevice)) {
|
||||
// The only way netFilter != filter is if linear filtering is requested and we
|
||||
// haven't yet found a quad that requires linear filtering (so net is still
|
||||
// nearest).
|
||||
SkASSERT(netFilter == GrSamplerState::Filter::kNearest &&
|
||||
filter == GrSamplerState::Filter::kLinear);
|
||||
netFilter = GrSamplerState::Filter::kLinear;
|
||||
if (netFilter != filter || netMM != mm) {
|
||||
// The only way netFilter != filter is if linear is requested and we haven't yet
|
||||
// found a quad that requires linear (so net is still nearest). Similar for mip
|
||||
// mapping.
|
||||
SkASSERT(netFilter <= filter);
|
||||
SkASSERT(netMM <= mm);
|
||||
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
|
||||
@ -970,6 +999,9 @@ private:
|
||||
if (fMetadata.filter() != that->fMetadata.filter()) {
|
||||
return CombineResult::kCannotCombine;
|
||||
}
|
||||
if (fMetadata.mipmapMode() != that->fMetadata.mipmapMode()) {
|
||||
return CombineResult::kCannotCombine;
|
||||
}
|
||||
if (fMetadata.fSwizzle != that->fMetadata.fSwizzle) {
|
||||
return CombineResult::kCannotCombine;
|
||||
}
|
||||
@ -1028,6 +1060,7 @@ std::unique_ptr<GrDrawOp> GrTextureOp::Make(GrRecordingContext* context,
|
||||
SkAlphaType alphaType,
|
||||
sk_sp<GrColorSpaceXform> textureXform,
|
||||
GrSamplerState::Filter filter,
|
||||
GrSamplerState::MipmapMode mm,
|
||||
const SkPMColor4f& color,
|
||||
Saturate saturate,
|
||||
SkBlendMode blendMode,
|
||||
@ -1040,13 +1073,18 @@ std::unique_ptr<GrDrawOp> GrTextureOp::Make(GrRecordingContext* context,
|
||||
subset = nullptr;
|
||||
}
|
||||
|
||||
if (filter != GrSamplerState::Filter::kNearest &&
|
||||
!filter_has_effect(quad->fLocal, quad->fDevice)) {
|
||||
filter = GrSamplerState::Filter::kNearest;
|
||||
if (filter != GrSamplerState::Filter::kNearest || mm != GrSamplerState::MipmapMode::kNone) {
|
||||
auto [mustFilter, mustMM] = filter_and_mm_have_effect(quad->fLocal, quad->fDevice);
|
||||
if (!mustFilter) {
|
||||
filter = GrSamplerState::Filter::kNearest;
|
||||
}
|
||||
if (!mustMM) {
|
||||
mm = GrSamplerState::MipmapMode::kNone;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
} else {
|
||||
// Emulate complex blending using GrFillRectOp
|
||||
@ -1086,6 +1124,7 @@ public:
|
||||
GrRecordingContext* context,
|
||||
int numEntries,
|
||||
GrSamplerState::Filter filter,
|
||||
GrSamplerState::MipmapMode mm,
|
||||
GrTextureOp::Saturate saturate,
|
||||
SkCanvas::SrcRectConstraint constraint,
|
||||
const SkMatrix& viewMatrix,
|
||||
@ -1094,20 +1133,27 @@ public:
|
||||
, fClip(clip)
|
||||
, fContext(context)
|
||||
, fFilter(filter)
|
||||
, fMipmapMode(mm)
|
||||
, fSaturate(saturate)
|
||||
, fConstraint(constraint)
|
||||
, fViewMatrix(viewMatrix)
|
||||
, fTextureColorSpaceXform(textureColorSpaceXform)
|
||||
, fNumLeft(numEntries) {
|
||||
}
|
||||
, fNumLeft(numEntries) {}
|
||||
|
||||
void createOp(GrRenderTargetContext::TextureSetEntry set[],
|
||||
int clumpSize,
|
||||
GrAAType aaType) {
|
||||
int clumpProxyCount = proxy_run_count(&set[fNumClumped], clumpSize);
|
||||
std::unique_ptr<GrDrawOp> op = TextureOp::Make(fContext, &set[fNumClumped], clumpSize,
|
||||
clumpProxyCount, fFilter, fSaturate, aaType,
|
||||
fConstraint, fViewMatrix,
|
||||
std::unique_ptr<GrDrawOp> op = TextureOp::Make(fContext,
|
||||
&set[fNumClumped],
|
||||
clumpSize,
|
||||
clumpProxyCount,
|
||||
fFilter,
|
||||
fMipmapMode,
|
||||
fSaturate,
|
||||
aaType,
|
||||
fConstraint,
|
||||
fViewMatrix,
|
||||
fTextureColorSpaceXform);
|
||||
fRTC->addDrawOp(fClip, std::move(op));
|
||||
|
||||
@ -1123,6 +1169,7 @@ private:
|
||||
const GrClip* fClip;
|
||||
GrRecordingContext* fContext;
|
||||
GrSamplerState::Filter fFilter;
|
||||
GrSamplerState::MipmapMode fMipmapMode;
|
||||
GrTextureOp::Saturate fSaturate;
|
||||
SkCanvas::SrcRectConstraint fConstraint;
|
||||
const SkMatrix& fViewMatrix;
|
||||
@ -1140,6 +1187,7 @@ void GrTextureOp::AddTextureSetOps(GrRenderTargetContext* rtc,
|
||||
int cnt,
|
||||
int proxyRunCnt,
|
||||
GrSamplerState::Filter filter,
|
||||
GrSamplerState::MipmapMode mm,
|
||||
Saturate saturate,
|
||||
SkBlendMode blendMode,
|
||||
GrAAType aaType,
|
||||
@ -1181,8 +1229,7 @@ void GrTextureOp::AddTextureSetOps(GrRenderTargetContext* rtc,
|
||||
? &set[i].fSrcRect : nullptr;
|
||||
|
||||
auto op = Make(context, set[i].fProxyView, set[i].fSrcAlphaType, textureColorSpaceXform,
|
||||
filter, set[i].fColor, saturate, blendMode, aaType,
|
||||
&quad, subset);
|
||||
filter, mm, set[i].fColor, saturate, blendMode, aaType, &quad, subset);
|
||||
rtc->addDrawOp(clip, std::move(op));
|
||||
}
|
||||
return;
|
||||
@ -1192,13 +1239,13 @@ void GrTextureOp::AddTextureSetOps(GrRenderTargetContext* rtc,
|
||||
// needed to clump things together.
|
||||
if (cnt <= std::min(GrResourceProvider::MaxNumNonAAQuads(),
|
||||
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));
|
||||
rtc->addDrawOp(clip, std::move(op));
|
||||
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));
|
||||
|
||||
// kNone and kMSAA never get altered
|
||||
@ -1292,11 +1339,13 @@ GR_DRAW_OP_TEST_DEFINE(TextureOp) {
|
||||
SkMatrix viewMatrix = GrTest::TestMatrixPreservesRightAngles(random);
|
||||
SkPMColor4f color = SkPMColor4f::FromBytes_RGBA(SkColorToPremulGrColor(random->nextU()));
|
||||
GrSamplerState::Filter filter = (GrSamplerState::Filter)random->nextULessThan(
|
||||
static_cast<uint32_t>(GrSamplerState::Filter::kMipMap) + 1);
|
||||
while (mipMapped == GrMipmapped::kNo && filter == GrSamplerState::Filter::kMipMap) {
|
||||
filter = (GrSamplerState::Filter)random->nextULessThan(
|
||||
static_cast<uint32_t>(GrSamplerState::Filter::kMipMap) + 1);
|
||||
static_cast<uint32_t>(GrSamplerState::Filter::kLast) + 1);
|
||||
GrSamplerState::MipmapMode mm = GrSamplerState::MipmapMode::kNone;
|
||||
if (mipMapped == GrMipmapped::kYes) {
|
||||
mm = (GrSamplerState::MipmapMode)random->nextULessThan(
|
||||
static_cast<uint32_t>(GrSamplerState::MipmapMode::kLast) + 1);
|
||||
}
|
||||
|
||||
auto texXform = GrTest::TestColorXform(random);
|
||||
GrAAType aaType = GrAAType::kNone;
|
||||
if (random->nextBool()) {
|
||||
@ -1317,8 +1366,8 @@ GR_DRAW_OP_TEST_DEFINE(TextureOp) {
|
||||
|
||||
DrawQuad quad = {GrQuad::MakeFromRect(rect, viewMatrix), GrQuad(srcRect), aaFlags};
|
||||
return GrTextureOp::Make(context, std::move(proxyView), alphaType, std::move(texXform), filter,
|
||||
color, saturate, SkBlendMode::kSrcOver, aaType,
|
||||
&quad, useSubset ? &srcRect : nullptr);
|
||||
mm, color, saturate, SkBlendMode::kSrcOver, aaType, &quad,
|
||||
useSubset ? &srcRect : nullptr);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -45,6 +45,7 @@ public:
|
||||
SkAlphaType srcAlphaType,
|
||||
sk_sp<GrColorSpaceXform>,
|
||||
GrSamplerState::Filter,
|
||||
GrSamplerState::MipmapMode,
|
||||
const SkPMColor4f&,
|
||||
Saturate,
|
||||
SkBlendMode,
|
||||
@ -62,6 +63,7 @@ public:
|
||||
int cnt,
|
||||
int proxyRunCnt,
|
||||
GrSamplerState::Filter,
|
||||
GrSamplerState::MipmapMode,
|
||||
Saturate,
|
||||
SkBlendMode,
|
||||
GrAAType,
|
||||
|
@ -10,8 +10,7 @@
|
||||
#include "src/gpu/vk/GrVkGpu.h"
|
||||
#include "src/gpu/vk/GrVkSamplerYcbcrConversion.h"
|
||||
|
||||
static inline VkSamplerAddressMode wrap_mode_to_vk_sampler_address(
|
||||
GrSamplerState::WrapMode wrapMode) {
|
||||
static VkSamplerAddressMode wrap_mode_to_vk_sampler_address(GrSamplerState::WrapMode wrapMode) {
|
||||
switch (wrapMode) {
|
||||
case GrSamplerState::WrapMode::kClamp:
|
||||
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:
|
||||
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,
|
||||
@ -45,7 +53,7 @@ GrVkSampler* GrVkSampler::Create(GrVkGpu* gpu, GrSamplerState samplerState,
|
||||
createInfo.flags = 0;
|
||||
createInfo.magFilter = vkMagFilterModes[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.addressModeV = wrap_mode_to_vk_sampler_address(samplerState.wrapModeY());
|
||||
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
|
||||
// the minFilter on mip level 0.
|
||||
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.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
|
||||
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
|
||||
// quality setting. This completely ignores the complexity of the drawVertices case
|
||||
// where explicit local coords are provided by the caller.
|
||||
bool doBicubic;
|
||||
GrSamplerState::Filter fm = GrSkFilterQualityToGrFilterMode(
|
||||
fImage->width(), fImage->height(), this->resolveFiltering(args.fFilterQuality),
|
||||
args.fMatrixProvider.localToDevice(), *lm,
|
||||
args.fContext->priv().options().fSharpenMipmappedTextures, &doBicubic);
|
||||
bool sharpen = args.fContext->priv().options().fSharpenMipmappedTextures;
|
||||
auto [fm, mm, bicubic] = GrInterpretFilterQuality(fImage->dimensions(),
|
||||
this->resolveFiltering(args.fFilterQuality),
|
||||
args.fMatrixProvider.localToDevice(),
|
||||
*lm,
|
||||
sharpen);
|
||||
std::unique_ptr<GrFragmentProcessor> fp;
|
||||
if (doBicubic) {
|
||||
if (bicubic) {
|
||||
fp = producer->createBicubicFragmentProcessor(lmInverse, nullptr, nullptr, wmX, wmY);
|
||||
} else {
|
||||
fp = producer->createFragmentProcessor(lmInverse, nullptr, nullptr, {wmX, wmY, fm});
|
||||
fp = producer->createFragmentProcessor(lmInverse, nullptr, nullptr, {wmX, wmY, fm, mm});
|
||||
}
|
||||
if (fp) {
|
||||
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);
|
||||
}
|
||||
|
||||
GrTextureOp::AddTextureSetOps(rtc.get(), nullptr, dContext, set, requestedTotNumQuads,
|
||||
requestedTotNumQuads, // We alternate so proxyCnt == cnt
|
||||
GrTextureOp::AddTextureSetOps(rtc.get(),
|
||||
nullptr,
|
||||
dContext,
|
||||
set,
|
||||
requestedTotNumQuads,
|
||||
requestedTotNumQuads, // We alternate so proxyCnt == cnt
|
||||
GrSamplerState::Filter::kNearest,
|
||||
GrSamplerState::MipmapMode::kNone,
|
||||
GrTextureOp::Saturate::kYes,
|
||||
blendMode,
|
||||
overallAA,
|
||||
SkCanvas::kStrict_SrcRectConstraint,
|
||||
SkMatrix::I(), nullptr);
|
||||
SkMatrix::I(),
|
||||
nullptr);
|
||||
|
||||
GrOpsTask* opsTask = rtc->testingOnly_PeekLastOpsTask();
|
||||
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'.
|
||||
static std::unique_ptr<GrRenderTargetContext> draw_mipmap_into_new_render_target(
|
||||
GrRecordingContext* context, GrProxyProvider* proxyProvider, GrColorType colorType,
|
||||
SkAlphaType alphaType, GrSurfaceProxyView mipmapView, GrSamplerState::Filter filter) {
|
||||
sk_sp<GrSurfaceProxy> renderTarget = proxyProvider->createProxy(
|
||||
mipmapView.proxy()->backendFormat(), {1, 1}, GrRenderable::kYes, 1, GrMipmapped::kNo,
|
||||
SkBackingFit::kApprox, SkBudgeted::kYes, GrProtected::kNo);
|
||||
GrRecordingContext* context,
|
||||
GrProxyProvider* proxyProvider,
|
||||
GrColorType colorType,
|
||||
SkAlphaType alphaType,
|
||||
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(
|
||||
context, colorType, nullptr, std::move(renderTarget), kTopLeft_GrSurfaceOrigin,
|
||||
nullptr);
|
||||
auto rtc = GrRenderTargetContext::Make(context,
|
||||
colorType,
|
||||
nullptr,
|
||||
std::move(renderTarget),
|
||||
kTopLeft_GrSurfaceOrigin,
|
||||
nullptr);
|
||||
|
||||
rtc->drawTexture(nullptr, std::move(mipmapView), alphaType, filter, SkBlendMode::kSrcOver,
|
||||
{1,1,1,1}, SkRect::MakeWH(4, 4), SkRect::MakeWH(1,1), GrAA::kYes,
|
||||
GrQuadAAFlags::kAll, SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(),
|
||||
rtc->drawTexture(nullptr,
|
||||
std::move(mipmapView),
|
||||
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);
|
||||
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.
|
||||
DEF_GPUTEST(GrManyDependentsMipMappedTest, reporter, /* options */) {
|
||||
using Enable = GrContextOptions::Enable;
|
||||
using Filter = GrSamplerState::Filter;
|
||||
using MipmapMode = GrSamplerState::MipmapMode;
|
||||
|
||||
for (auto enableSortingAndReduction : {Enable::kYes, Enable::kNo}) {
|
||||
GrMockOptions mockOptions;
|
||||
@ -421,7 +444,7 @@ DEF_GPUTEST(GrManyDependentsMipMappedTest, reporter, /* options */) {
|
||||
|
||||
// Draw the dirty mipmap texture into a render target.
|
||||
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());
|
||||
|
||||
// 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.
|
||||
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());
|
||||
|
||||
// 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.
|
||||
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.
|
||||
// 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.
|
||||
rtc2 = draw_mipmap_into_new_render_target(context.get(), proxyProvider, colorType,
|
||||
alphaType, std::move(mipmapView),
|
||||
Filter::kMipMap);
|
||||
MipmapMode::kLinear);
|
||||
rtc2Task = sk_ref_sp(rtc2->testingOnly_PeekLastOpsTask());
|
||||
|
||||
// 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(
|
||||
backendFormat, GrColorType::kRGBA_8888);
|
||||
GrSurfaceProxyView view(std::move(proxy), kTopLeft_GrSurfaceOrigin, readSwizzle);
|
||||
rtc->drawTexture(nullptr, view, kPremul_SkAlphaType,
|
||||
GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver,
|
||||
SkPMColor4f(), SkRect::MakeWH(w, h), SkRect::MakeWH(w, h),
|
||||
GrAA::kNo, GrQuadAAFlags::kNone, SkCanvas::kFast_SrcRectConstraint,
|
||||
SkMatrix::I(), nullptr);
|
||||
rtc->drawTexture(nullptr,
|
||||
view,
|
||||
kPremul_SkAlphaType,
|
||||
GrSamplerState::Filter::kNearest,
|
||||
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
|
||||
// texture not purgeable.
|
||||
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());
|
||||
|
||||
// This time we move the proxy into the draw.
|
||||
rtc->drawTexture(nullptr, std::move(view), kPremul_SkAlphaType,
|
||||
GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver,
|
||||
SkPMColor4f(), SkRect::MakeWH(w, h), SkRect::MakeWH(w, h),
|
||||
GrAA::kNo, GrQuadAAFlags::kNone,
|
||||
SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(), nullptr);
|
||||
rtc->drawTexture(nullptr,
|
||||
std::move(view),
|
||||
kPremul_SkAlphaType,
|
||||
GrSamplerState::Filter::kNearest,
|
||||
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());
|
||||
dContext->flushAndSubmit();
|
||||
dContext->priv().getGpu()->testingOnly_flushGpuAndSync();
|
||||
@ -640,12 +658,20 @@ DEF_GPUTEST(TextureIdleProcTest, reporter, options) {
|
||||
proxy->backendFormat(), GrColorType::kRGBA_8888);
|
||||
GrSurfaceProxyView view(std::move(proxy), kTopLeft_GrSurfaceOrigin,
|
||||
swizzle);
|
||||
rtc->drawTexture(
|
||||
nullptr, std::move(view), kPremul_SkAlphaType,
|
||||
GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver,
|
||||
SkPMColor4f(), SkRect::MakeWH(w, h), SkRect::MakeWH(w, h),
|
||||
GrAA::kNo, GrQuadAAFlags::kNone,
|
||||
SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(), nullptr);
|
||||
rtc->drawTexture(nullptr,
|
||||
std::move(view),
|
||||
kPremul_SkAlphaType,
|
||||
GrSamplerState::Filter::kNearest,
|
||||
GrSamplerState::MipmapMode::kNone,
|
||||
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) {
|
||||
dContext->flushAndSubmit();
|
||||
}
|
||||
|
@ -28,17 +28,17 @@ static void test_basic_draw_as_src(skiatest::Reporter* reporter, GrRecordingCont
|
||||
SkAlphaType alphaType, uint32_t expectedPixelValues[]) {
|
||||
auto rtContext = GrRenderTargetContext::Make(
|
||||
context, colorType, nullptr, SkBackingFit::kExact, rectView.proxy()->dimensions());
|
||||
for (auto filter : {GrSamplerState::Filter::kNearest,
|
||||
GrSamplerState::Filter::kLinear,
|
||||
GrSamplerState::Filter::kMipMap}) {
|
||||
rtContext->clear(SkPMColor4f::FromBytes_RGBA(0xDDCCBBAA));
|
||||
auto fp = GrTextureEffect::Make(rectView, alphaType, SkMatrix::I(), filter);
|
||||
GrPaint paint;
|
||||
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
|
||||
paint.setColorFragmentProcessor(std::move(fp));
|
||||
rtContext->drawPaint(nullptr, std::move(paint), SkMatrix::I());
|
||||
TestReadPixels(reporter, rtContext.get(), expectedPixelValues,
|
||||
"RectangleTexture-basic-draw");
|
||||
for (auto filter : {GrSamplerState::Filter::kNearest, GrSamplerState::Filter::kLinear}) {
|
||||
for (auto mm : {GrSamplerState::MipmapMode::kNone, GrSamplerState::MipmapMode::kLinear}) {
|
||||
rtContext->clear(SkPMColor4f::FromBytes_RGBA(0xDDCCBBAA));
|
||||
auto fp = GrTextureEffect::Make(rectView, alphaType, SkMatrix::I(), filter, mm);
|
||||
GrPaint paint;
|
||||
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
|
||||
paint.setColorFragmentProcessor(std::move(fp));
|
||||
rtContext->drawPaint(nullptr, std::move(paint), SkMatrix::I());
|
||||
TestReadPixels(reporter, rtContext.get(), expectedPixelValues,
|
||||
"RectangleTexture-basic-draw");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user