std::unique_ptr<GrFragmentProcessor> GrTextureProducer::CreateFragmentProcessorForDomainAndFilter( sk_sp<GrTextureProxy> proxy, const SkMatrix& textureMatrix, DomainMode domainMode, const SkRect& domain, const GrSamplerState::Filter* filterOrNullForBicubic) { SkASSERT(kTightCopy_DomainMode != domainMode); if (filterOrNullForBicubic) { if (kDomain_DomainMode == domainMode) { return GrTextureDomainEffect::Make(std::move(proxy), textureMatrix, domain, GrTextureDomain::kClamp_Mode, *filterOrNullForBicubic); } else { GrSamplerState samplerState(GrSamplerState::WrapMode::kClamp, *filterOrNullForBicubic); return GrSimpleTextureEffect::Make(std::move(proxy), textureMatrix, samplerState); } } else { if (kDomain_DomainMode == domainMode) { return GrBicubicEffect::Make(std::move(proxy), textureMatrix, domain); } else { static const GrSamplerState::WrapMode kClampClamp[] = { GrSamplerState::WrapMode::kClamp, GrSamplerState::WrapMode::kClamp}; return GrBicubicEffect::Make(std::move(proxy), textureMatrix, kClampClamp); } } }
sk_sp<GrGeometryProcessor> GrBitmapTextGeoProc::TestCreate(GrProcessorTestData* d) { int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx : GrProcessorUnitTest::kAlphaTextureIdx; sk_sp<GrTextureProxy> proxies[kMaxTextures] = { d->textureProxy(texIdx), nullptr, nullptr, nullptr }; GrSamplerState::WrapMode wrapModes[2]; GrTest::TestWrapModes(d->fRandom, wrapModes); GrSamplerState samplerState(wrapModes, d->fRandom->nextBool() ? GrSamplerState::Filter::kBilerp : GrSamplerState::Filter::kNearest); GrMaskFormat format = kARGB_GrMaskFormat; // init to avoid warning switch (d->fRandom->nextULessThan(3)) { case 0: format = kA8_GrMaskFormat; break; case 1: format = kA565_GrMaskFormat; break; case 2: format = kARGB_GrMaskFormat; break; } return GrBitmapTextGeoProc::Make(*d->caps()->shaderCaps(), GrRandomColor(d->fRandom), proxies, 1, samplerState, format, GrTest::TestMatrix(d->fRandom), d->fRandom->nextBool()); }
sk_sp<GrGeometryProcessor> GrDistanceFieldLCDTextGeoProc::TestCreate(GrProcessorTestData* d) { int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx : GrProcessorUnitTest::kAlphaTextureIdx; sk_sp<GrTextureProxy> proxies[kMaxTextures] = { d->textureProxy(texIdx), nullptr, nullptr, nullptr }; GrSamplerState::WrapMode wrapModes[2]; GrTest::TestWrapModes(d->fRandom, wrapModes); GrSamplerState samplerState(wrapModes, d->fRandom->nextBool() ? GrSamplerState::Filter::kBilerp : GrSamplerState::Filter::kNearest); DistanceAdjust wa = { 0.0f, 0.1f, -0.1f }; uint32_t flags = kUseLCD_DistanceFieldEffectFlag; flags |= d->fRandom->nextBool() ? kSimilarity_DistanceFieldEffectFlag : 0; if (flags & kSimilarity_DistanceFieldEffectFlag) { flags |= d->fRandom->nextBool() ? kScaleOnly_DistanceFieldEffectFlag : 0; } flags |= d->fRandom->nextBool() ? kBGR_DistanceFieldEffectFlag : 0; SkMatrix localMatrix = GrTest::TestMatrix(d->fRandom); return GrDistanceFieldLCDTextGeoProc::Make(proxies, samplerState, wa, flags, localMatrix); }
sk_sp<GrGeometryProcessor> GrDistanceFieldPathGeoProc::TestCreate(GrProcessorTestData* d) { int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx : GrProcessorUnitTest::kAlphaTextureIdx; sk_sp<GrTextureProxy> proxies[kMaxTextures] = { d->textureProxy(texIdx), nullptr, nullptr, nullptr }; GrSamplerState::WrapMode wrapModes[2]; GrTest::TestWrapModes(d->fRandom, wrapModes); GrSamplerState samplerState(wrapModes, d->fRandom->nextBool() ? GrSamplerState::Filter::kBilerp : GrSamplerState::Filter::kNearest); uint32_t flags = 0; flags |= d->fRandom->nextBool() ? kSimilarity_DistanceFieldEffectFlag : 0; if (flags & kSimilarity_DistanceFieldEffectFlag) { flags |= d->fRandom->nextBool() ? kScaleOnly_DistanceFieldEffectFlag : 0; } return GrDistanceFieldPathGeoProc::Make(GrTest::TestMatrix(d->fRandom), proxies, samplerState, flags); }
sk_sp<GrGeometryProcessor> GrDistanceFieldA8TextGeoProc::TestCreate(GrProcessorTestData* d) { int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx : GrProcessorUnitTest::kAlphaTextureIdx; sk_sp<GrTextureProxy> proxies[kMaxTextures] = { d->textureProxy(texIdx), nullptr, nullptr, nullptr }; GrSamplerState::WrapMode wrapModes[2]; GrTest::TestWrapModes(d->fRandom, wrapModes); GrSamplerState samplerState(wrapModes, d->fRandom->nextBool() ? GrSamplerState::Filter::kBilerp : GrSamplerState::Filter::kNearest); uint32_t flags = 0; flags |= d->fRandom->nextBool() ? kSimilarity_DistanceFieldEffectFlag : 0; if (flags & kSimilarity_DistanceFieldEffectFlag) { flags |= d->fRandom->nextBool() ? kScaleOnly_DistanceFieldEffectFlag : 0; } SkMatrix localMatrix = GrTest::TestMatrix(d->fRandom); #ifdef SK_GAMMA_APPLY_TO_A8 float lum = d->fRandom->nextF(); #endif return GrDistanceFieldA8TextGeoProc::Make(proxies, samplerState, #ifdef SK_GAMMA_APPLY_TO_A8 lum, #endif flags, localMatrix); }
sk_sp<GrTextureProxy> GrTextureProducer::CopyOnGpu(GrContext* context, sk_sp<GrTextureProxy> inputProxy, const CopyParams& copyParams, bool dstWillRequireMipMaps) { SkASSERT(context); const SkRect dstRect = SkRect::MakeIWH(copyParams.fWidth, copyParams.fHeight); GrMipMapped mipMapped = dstWillRequireMipMaps ? GrMipMapped::kYes : GrMipMapped::kNo; SkRect localRect = SkRect::MakeWH(inputProxy->width(), inputProxy->height()); bool needsDomain = false; bool resizing = false; if (copyParams.fFilter != GrSamplerState::Filter::kNearest) { bool resizing = localRect.width() != dstRect.width() || localRect.height() != dstRect.height(); needsDomain = resizing && !GrProxyProvider::IsFunctionallyExact(inputProxy.get()); } if (copyParams.fFilter == GrSamplerState::Filter::kNearest && !needsDomain && !resizing && dstWillRequireMipMaps) { sk_sp<GrTextureProxy> proxy = GrCopyBaseMipMapToTextureProxy(context, inputProxy.get()); if (proxy) { return proxy; } } sk_sp<GrRenderTargetContext> copyRTC = context->contextPriv().makeDeferredRenderTargetContextWithFallback( SkBackingFit::kExact, dstRect.width(), dstRect.height(), inputProxy->config(), nullptr, 1, mipMapped, inputProxy->origin()); if (!copyRTC) { return nullptr; } GrPaint paint; if (needsDomain) { const SkRect domain = localRect.makeInset(0.5f, 0.5f); // This would cause us to read values from outside the subset. Surely, the caller knows // better! SkASSERT(copyParams.fFilter != GrSamplerState::Filter::kMipMap); paint.addColorFragmentProcessor( GrTextureDomainEffect::Make(std::move(inputProxy), SkMatrix::I(), domain, GrTextureDomain::kClamp_Mode, copyParams.fFilter)); } else { GrSamplerState samplerState(GrSamplerState::WrapMode::kClamp, copyParams.fFilter); paint.addColorTextureProcessor(std::move(inputProxy), SkMatrix::I(), samplerState); } paint.setPorterDuffXPFactory(SkBlendMode::kSrc); copyRTC->fillRectToRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), dstRect, localRect); return copyRTC->asTextureProxyRef(); }
std::unique_ptr<GrFragmentProcessor> SkImageShader::asFragmentProcessor( const GrFPArgs& args) const { const auto lm = this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix); SkMatrix lmInverse; if (!lm->invert(&lmInverse)) { return nullptr; } GrSamplerState::WrapMode wrapModes[] = {tile_mode_to_wrap_mode(fTileModeX), tile_mode_to_wrap_mode(fTileModeY)}; // Must set wrap and filter on the sampler before requesting a texture. In two places 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 textureFilterMode = GrSkFilterQualityToGrFilterMode( args.fFilterQuality, *args.fViewMatrix, *lm, args.fContext->contextPriv().sharpenMipmappedTextures(), &doBicubic); GrSamplerState samplerState(wrapModes, textureFilterMode); sk_sp<SkColorSpace> texColorSpace; SkScalar scaleAdjust[2] = { 1.0f, 1.0f }; sk_sp<GrTextureProxy> proxy(as_IB(fImage)->asTextureProxyRef( args.fContext, samplerState, args.fDstColorSpaceInfo->colorSpace(), &texColorSpace, scaleAdjust)); if (!proxy) { return nullptr; } GrPixelConfig config = proxy->config(); bool isAlphaOnly = GrPixelConfigIsAlphaOnly(config); lmInverse.postScale(scaleAdjust[0], scaleAdjust[1]); std::unique_ptr<GrFragmentProcessor> inner; if (doBicubic) { inner = GrBicubicEffect::Make(std::move(proxy), lmInverse, wrapModes); } else { inner = GrSimpleTextureEffect::Make(std::move(proxy), lmInverse, samplerState); } inner = GrColorSpaceXformEffect::Make(std::move(inner), texColorSpace.get(), config, args.fDstColorSpaceInfo->colorSpace()); if (isAlphaOnly) { return inner; } return GrFragmentProcessor::MulChildByInputAlpha(std::move(inner)); }
bool TextureArraysWindow::CreateScene() { // Create the shaders and associated resources. std::string filename = mEnvironment.GetPath("TextureArrays.hlsl"); std::shared_ptr<VisualProgram> program = mProgramFactory.CreateFromFiles(filename, filename, ""); if (!program) { return false; } // Create a vertex buffer for a single triangle. The PNG is stored in // left-handed coordinates. The texture coordinates are chosen to reflect // the texture in the y-direction. struct Vertex { Vector3<float> position; Vector2<float> tcoord; }; VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); vformat.Bind(VA_TEXCOORD, DF_R32G32_FLOAT, 0); std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat, 4)); Vertex* vertex = vbuffer->Get<Vertex>(); vertex[0].position = { 0.0f, 0.0f, 0.0f }; vertex[0].tcoord = { 0.0f, 1.0f }; vertex[1].position = { 1.0f, 0.0f, 0.0f }; vertex[1].tcoord = { 1.0f, 1.0f }; vertex[2].position = { 0.0f, 1.0f, 0.0f }; vertex[2].tcoord = { 0.0f, 0.0f }; vertex[3].position = { 1.0f, 1.0f, 0.0f }; vertex[3].tcoord = { 1.0f, 0.0f }; // Create an indexless buffer for a triangle mesh with two triangles. std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer(IP_TRISTRIP, 2)); // Create an effect for the vertex and pixel shaders. The texture is // bilinearly filtered and the texture coordinates are clamped to [0,1]^2. std::shared_ptr<ConstantBuffer> cbuffer(new ConstantBuffer( sizeof(Matrix4x4<float>), true)); program->GetVShader()->Set("PVWMatrix", cbuffer); std::shared_ptr<PixelShader> pshader = program->GetPShader(); std::shared_ptr<Texture1Array> t1array(new Texture1Array(2, DF_R8G8B8A8_UNORM, 2)); unsigned int* t1data = t1array->Get<unsigned int>(); t1data[0] = 0xFF000000; t1data[1] = 0xFFFFFFFF; pshader->Set("myTexture1", t1array); Texture2* stoneTexture = WICFileIO::Load( mEnvironment.GetPath("StoneWall.png"), false); std::shared_ptr<Texture2Array> t2array(new Texture2Array(2, DF_R8G8B8A8_UNORM, 256, 256)); unsigned char* t2data = t2array->Get<unsigned char>(); size_t const numBytes = stoneTexture->GetNumBytes(); Memcpy(t2data, stoneTexture->GetData(), numBytes); t2data += numBytes; delete stoneTexture; for (size_t i = 0; i < numBytes; ++i) { *t2data++ = static_cast<unsigned char>(rand() % 256); } pshader->Set("myTexture2", t2array); std::shared_ptr<SamplerState> samplerState(new SamplerState()); samplerState->filter = SamplerState::MIN_L_MAG_L_MIP_P; samplerState->mode[0] = SamplerState::CLAMP; samplerState->mode[1] = SamplerState::CLAMP; pshader->Set("mySampler", samplerState); std::shared_ptr<VisualEffect> effect = std::make_shared<VisualEffect>(program); // Create the geometric object for drawing. Translate it so that its // center of mass is at the origin. This supports virtual trackball // motion about the object "center". mSquare = std::make_shared<Visual>(vbuffer, ibuffer, effect); mSquare->localTransform.SetTranslation(-0.5f, -0.5f, 0.0f); // Enable automatic updates of pvw-matrices and w-matrices. mCameraRig.Subscribe(mSquare->worldTransform, cbuffer); mTrackball.Attach(mSquare); mTrackball.Update(); return true; }