SkDisplacementMapEffect.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  1. /*
  2. * Copyright 2013 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "include/effects/SkDisplacementMapEffect.h"
  8. #include "include/core/SkBitmap.h"
  9. #include "include/core/SkUnPreMultiply.h"
  10. #include "include/private/SkColorData.h"
  11. #include "src/core/SkImageFilterPriv.h"
  12. #include "src/core/SkReadBuffer.h"
  13. #include "src/core/SkSpecialImage.h"
  14. #include "src/core/SkWriteBuffer.h"
  15. #if SK_SUPPORT_GPU
  16. #include "include/gpu/GrTexture.h"
  17. #include "include/private/GrRecordingContext.h"
  18. #include "src/gpu/GrCaps.h"
  19. #include "src/gpu/GrClip.h"
  20. #include "src/gpu/GrColorSpaceXform.h"
  21. #include "src/gpu/GrCoordTransform.h"
  22. #include "src/gpu/GrRecordingContextPriv.h"
  23. #include "src/gpu/GrRenderTargetContext.h"
  24. #include "src/gpu/GrTextureProxy.h"
  25. #include "src/gpu/SkGr.h"
  26. #include "src/gpu/effects/GrTextureDomain.h"
  27. #include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
  28. #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
  29. #include "src/gpu/glsl/GrGLSLProgramDataManager.h"
  30. #include "src/gpu/glsl/GrGLSLUniformHandler.h"
  31. #endif
  32. namespace {
  33. #define kChannelSelectorKeyBits 3 // Max value is 4, so 3 bits are required at most
  34. // Shift values to extract channels from an SkColor (SkColorGetR, SkColorGetG, etc)
  35. const uint8_t gChannelTypeToShift[] = {
  36. 0, // unknown
  37. 16, // R
  38. 8, // G
  39. 0, // B
  40. 24, // A
  41. };
  42. struct Extractor {
  43. Extractor(SkDisplacementMapEffect::ChannelSelectorType typeX,
  44. SkDisplacementMapEffect::ChannelSelectorType typeY)
  45. : fShiftX(gChannelTypeToShift[typeX])
  46. , fShiftY(gChannelTypeToShift[typeY])
  47. {}
  48. unsigned fShiftX, fShiftY;
  49. unsigned getX(SkColor c) const { return (c >> fShiftX) & 0xFF; }
  50. unsigned getY(SkColor c) const { return (c >> fShiftY) & 0xFF; }
  51. };
  52. void computeDisplacement(Extractor ex, const SkVector& scale, SkBitmap* dst,
  53. const SkBitmap& displ, const SkIPoint& offset,
  54. const SkBitmap& src,
  55. const SkIRect& bounds) {
  56. static const SkScalar Inv8bit = SkScalarInvert(255);
  57. const int srcW = src.width();
  58. const int srcH = src.height();
  59. const SkVector scaleForColor = SkVector::Make(scale.fX * Inv8bit, scale.fY * Inv8bit);
  60. const SkVector scaleAdj = SkVector::Make(SK_ScalarHalf - scale.fX * SK_ScalarHalf,
  61. SK_ScalarHalf - scale.fY * SK_ScalarHalf);
  62. SkPMColor* dstPtr = dst->getAddr32(0, 0);
  63. for (int y = bounds.top(); y < bounds.bottom(); ++y) {
  64. const SkPMColor* displPtr = displ.getAddr32(bounds.left() + offset.fX, y + offset.fY);
  65. for (int x = bounds.left(); x < bounds.right(); ++x, ++displPtr) {
  66. SkColor c = SkUnPreMultiply::PMColorToColor(*displPtr);
  67. SkScalar displX = scaleForColor.fX * ex.getX(c) + scaleAdj.fX;
  68. SkScalar displY = scaleForColor.fY * ex.getY(c) + scaleAdj.fY;
  69. // Truncate the displacement values
  70. const int32_t srcX = Sk32_sat_add(x, SkScalarTruncToInt(displX));
  71. const int32_t srcY = Sk32_sat_add(y, SkScalarTruncToInt(displY));
  72. *dstPtr++ = ((srcX < 0) || (srcX >= srcW) || (srcY < 0) || (srcY >= srcH)) ?
  73. 0 : *(src.getAddr32(srcX, srcY));
  74. }
  75. }
  76. }
  77. bool channel_selector_type_is_valid(SkDisplacementMapEffect::ChannelSelectorType cst) {
  78. switch (cst) {
  79. case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
  80. case SkDisplacementMapEffect::kR_ChannelSelectorType:
  81. case SkDisplacementMapEffect::kG_ChannelSelectorType:
  82. case SkDisplacementMapEffect::kB_ChannelSelectorType:
  83. case SkDisplacementMapEffect::kA_ChannelSelectorType:
  84. return true;
  85. default:
  86. break;
  87. }
  88. return false;
  89. }
  90. } // end namespace
  91. ///////////////////////////////////////////////////////////////////////////////
  92. sk_sp<SkImageFilter> SkDisplacementMapEffect::Make(ChannelSelectorType xChannelSelector,
  93. ChannelSelectorType yChannelSelector,
  94. SkScalar scale,
  95. sk_sp<SkImageFilter> displacement,
  96. sk_sp<SkImageFilter> color,
  97. const CropRect* cropRect) {
  98. if (!channel_selector_type_is_valid(xChannelSelector) ||
  99. !channel_selector_type_is_valid(yChannelSelector)) {
  100. return nullptr;
  101. }
  102. sk_sp<SkImageFilter> inputs[2] = { std::move(displacement), std::move(color) };
  103. return sk_sp<SkImageFilter>(new SkDisplacementMapEffect(xChannelSelector,
  104. yChannelSelector,
  105. scale, inputs, cropRect));
  106. }
  107. SkDisplacementMapEffect::SkDisplacementMapEffect(ChannelSelectorType xChannelSelector,
  108. ChannelSelectorType yChannelSelector,
  109. SkScalar scale,
  110. sk_sp<SkImageFilter> inputs[2],
  111. const CropRect* cropRect)
  112. : INHERITED(inputs, 2, cropRect)
  113. , fXChannelSelector(xChannelSelector)
  114. , fYChannelSelector(yChannelSelector)
  115. , fScale(scale) {
  116. }
  117. SkDisplacementMapEffect::~SkDisplacementMapEffect() {
  118. }
  119. sk_sp<SkFlattenable> SkDisplacementMapEffect::CreateProc(SkReadBuffer& buffer) {
  120. SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 2);
  121. ChannelSelectorType xsel = buffer.read32LE(kLast_ChannelSelectorType);
  122. ChannelSelectorType ysel = buffer.read32LE(kLast_ChannelSelectorType);
  123. SkScalar scale = buffer.readScalar();
  124. return Make(xsel, ysel, scale, common.getInput(0), common.getInput(1), &common.cropRect());
  125. }
  126. void SkDisplacementMapEffect::flatten(SkWriteBuffer& buffer) const {
  127. this->INHERITED::flatten(buffer);
  128. buffer.writeInt((int) fXChannelSelector);
  129. buffer.writeInt((int) fYChannelSelector);
  130. buffer.writeScalar(fScale);
  131. }
  132. #if SK_SUPPORT_GPU
  133. class GrDisplacementMapEffect : public GrFragmentProcessor {
  134. public:
  135. static std::unique_ptr<GrFragmentProcessor> Make(
  136. SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
  137. SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, SkVector scale,
  138. sk_sp<GrTextureProxy> displacement, const SkIRect& displSubset,
  139. const SkMatrix& offsetMatrix, sk_sp<GrTextureProxy> color, const SkIRect& colorSubset) {
  140. return std::unique_ptr<GrFragmentProcessor>(new GrDisplacementMapEffect(
  141. xChannelSelector, yChannelSelector, scale, std::move(displacement), displSubset,
  142. offsetMatrix, std::move(color), colorSubset));
  143. }
  144. ~GrDisplacementMapEffect() override;
  145. SkDisplacementMapEffect::ChannelSelectorType xChannelSelector() const {
  146. return fXChannelSelector;
  147. }
  148. SkDisplacementMapEffect::ChannelSelectorType yChannelSelector() const {
  149. return fYChannelSelector;
  150. }
  151. const SkVector& scale() const { return fScale; }
  152. const char* name() const override { return "DisplacementMap"; }
  153. const GrTextureDomain& domain() const { return fDomain; }
  154. std::unique_ptr<GrFragmentProcessor> clone() const override;
  155. private:
  156. GrDisplacementMapEffect(const GrDisplacementMapEffect&);
  157. GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
  158. void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
  159. bool onIsEqual(const GrFragmentProcessor&) const override;
  160. GrDisplacementMapEffect(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
  161. SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
  162. const SkVector& scale, sk_sp<GrTextureProxy> displacement,
  163. const SkIRect& displSubset, const SkMatrix& offsetMatrix,
  164. sk_sp<GrTextureProxy> color, const SkIRect& colorSubset);
  165. const TextureSampler& onTextureSampler(int i) const override {
  166. return IthTextureSampler(i, fDisplacementSampler, fColorSampler);
  167. }
  168. GR_DECLARE_FRAGMENT_PROCESSOR_TEST
  169. GrCoordTransform fDisplacementTransform;
  170. TextureSampler fDisplacementSampler;
  171. GrCoordTransform fColorTransform;
  172. GrTextureDomain fDomain;
  173. TextureSampler fColorSampler;
  174. SkDisplacementMapEffect::ChannelSelectorType fXChannelSelector;
  175. SkDisplacementMapEffect::ChannelSelectorType fYChannelSelector;
  176. SkVector fScale;
  177. typedef GrFragmentProcessor INHERITED;
  178. };
  179. #endif
  180. sk_sp<SkSpecialImage> SkDisplacementMapEffect::onFilterImage(SkSpecialImage* source,
  181. const Context& ctx,
  182. SkIPoint* offset) const {
  183. SkIPoint colorOffset = SkIPoint::Make(0, 0);
  184. sk_sp<SkSpecialImage> color(this->filterInput(1, source, ctx, &colorOffset));
  185. if (!color) {
  186. return nullptr;
  187. }
  188. SkIPoint displOffset = SkIPoint::Make(0, 0);
  189. // Creation of the displacement map should happen in a non-colorspace aware context. This
  190. // texture is a purely mathematical construct, so we want to just operate on the stored
  191. // values. Consider:
  192. // User supplies an sRGB displacement map. If we're rendering to a wider gamut, then we could
  193. // end up filtering the displacement map into that gamut, which has the effect of reducing
  194. // the amount of displacement that it represents (as encoded values move away from the
  195. // primaries).
  196. // With a more complex DAG attached to this input, it's not clear that working in ANY specific
  197. // color space makes sense, so we ignore color spaces (and gamma) entirely. This may not be
  198. // ideal, but it's at least consistent and predictable.
  199. Context displContext(ctx.ctm(), ctx.clipBounds(), ctx.cache(),
  200. OutputProperties(kN32_SkColorType, nullptr));
  201. sk_sp<SkSpecialImage> displ(this->filterInput(0, source, displContext, &displOffset));
  202. if (!displ) {
  203. return nullptr;
  204. }
  205. const SkIRect srcBounds = SkIRect::MakeXYWH(colorOffset.x(), colorOffset.y(),
  206. color->width(), color->height());
  207. // Both paths do bounds checking on color pixel access, we don't need to
  208. // pad the color bitmap to bounds here.
  209. SkIRect bounds;
  210. if (!this->applyCropRect(ctx, srcBounds, &bounds)) {
  211. return nullptr;
  212. }
  213. SkIRect displBounds;
  214. displ = this->applyCropRectAndPad(ctx, displ.get(), &displOffset, &displBounds);
  215. if (!displ) {
  216. return nullptr;
  217. }
  218. if (!bounds.intersect(displBounds)) {
  219. return nullptr;
  220. }
  221. const SkIRect colorBounds = bounds.makeOffset(-colorOffset.x(), -colorOffset.y());
  222. // If the offset overflowed (saturated) then we have to abort, as we need their
  223. // dimensions to be equal. See https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=7209
  224. if (colorBounds.size() != bounds.size()) {
  225. return nullptr;
  226. }
  227. SkVector scale = SkVector::Make(fScale, fScale);
  228. ctx.ctm().mapVectors(&scale, 1);
  229. #if SK_SUPPORT_GPU
  230. if (source->isTextureBacked()) {
  231. auto context = source->getContext();
  232. sk_sp<GrTextureProxy> colorProxy(color->asTextureProxyRef(context));
  233. sk_sp<GrTextureProxy> displProxy(displ->asTextureProxyRef(context));
  234. if (!colorProxy || !displProxy) {
  235. return nullptr;
  236. }
  237. const auto isProtected = colorProxy->isProtected() ? GrProtected::kYes : GrProtected::kNo;
  238. SkMatrix offsetMatrix = SkMatrix::MakeTrans(SkIntToScalar(colorOffset.fX - displOffset.fX),
  239. SkIntToScalar(colorOffset.fY - displOffset.fY));
  240. SkColorSpace* colorSpace = ctx.outputProperties().colorSpace();
  241. std::unique_ptr<GrFragmentProcessor> fp =
  242. GrDisplacementMapEffect::Make(fXChannelSelector,
  243. fYChannelSelector,
  244. scale,
  245. std::move(displProxy),
  246. displ->subset(),
  247. offsetMatrix,
  248. std::move(colorProxy),
  249. color->subset());
  250. fp = GrColorSpaceXformEffect::Make(std::move(fp), color->getColorSpace(),
  251. color->alphaType(), colorSpace);
  252. GrPaint paint;
  253. paint.addColorFragmentProcessor(std::move(fp));
  254. paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
  255. SkMatrix matrix;
  256. matrix.setTranslate(-SkIntToScalar(colorBounds.x()), -SkIntToScalar(colorBounds.y()));
  257. GrColorType colorType = SkColorTypeToGrColorType(ctx.outputProperties().colorType());
  258. sk_sp<GrRenderTargetContext> renderTargetContext(
  259. context->priv().makeDeferredRenderTargetContext(SkBackingFit::kApprox,
  260. bounds.width(),
  261. bounds.height(),
  262. colorType,
  263. sk_ref_sp(colorSpace),
  264. 1,
  265. GrMipMapped::kNo,
  266. kBottomLeft_GrSurfaceOrigin,
  267. nullptr,
  268. SkBudgeted::kYes,
  269. isProtected));
  270. if (!renderTargetContext) {
  271. return nullptr;
  272. }
  273. renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, matrix,
  274. SkRect::Make(colorBounds));
  275. offset->fX = bounds.left();
  276. offset->fY = bounds.top();
  277. return SkSpecialImage::MakeDeferredFromGpu(
  278. context,
  279. SkIRect::MakeWH(bounds.width(), bounds.height()),
  280. kNeedNewImageUniqueID_SpecialImage,
  281. renderTargetContext->asTextureProxyRef(),
  282. renderTargetContext->colorSpaceInfo().refColorSpace());
  283. }
  284. #endif
  285. SkBitmap colorBM, displBM;
  286. if (!color->getROPixels(&colorBM) || !displ->getROPixels(&displBM)) {
  287. return nullptr;
  288. }
  289. if ((colorBM.colorType() != kN32_SkColorType) ||
  290. (displBM.colorType() != kN32_SkColorType)) {
  291. return nullptr;
  292. }
  293. if (!colorBM.getPixels() || !displBM.getPixels()) {
  294. return nullptr;
  295. }
  296. SkImageInfo info = SkImageInfo::MakeN32(bounds.width(), bounds.height(),
  297. colorBM.alphaType());
  298. SkBitmap dst;
  299. if (!dst.tryAllocPixels(info)) {
  300. return nullptr;
  301. }
  302. computeDisplacement(Extractor(fXChannelSelector, fYChannelSelector), scale, &dst,
  303. displBM, colorOffset - displOffset, colorBM, colorBounds);
  304. offset->fX = bounds.left();
  305. offset->fY = bounds.top();
  306. return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(bounds.width(), bounds.height()),
  307. dst);
  308. }
  309. SkRect SkDisplacementMapEffect::computeFastBounds(const SkRect& src) const {
  310. SkRect bounds = this->getColorInput() ? this->getColorInput()->computeFastBounds(src) : src;
  311. bounds.outset(SkScalarAbs(fScale) * SK_ScalarHalf, SkScalarAbs(fScale) * SK_ScalarHalf);
  312. return bounds;
  313. }
  314. SkIRect SkDisplacementMapEffect::onFilterNodeBounds(const SkIRect& src, const SkMatrix& ctm,
  315. MapDirection, const SkIRect* inputRect) const {
  316. SkVector scale = SkVector::Make(fScale, fScale);
  317. ctm.mapVectors(&scale, 1);
  318. return src.makeOutset(SkScalarCeilToInt(SkScalarAbs(scale.fX) * SK_ScalarHalf),
  319. SkScalarCeilToInt(SkScalarAbs(scale.fY) * SK_ScalarHalf));
  320. }
  321. SkIRect SkDisplacementMapEffect::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
  322. MapDirection dir, const SkIRect* inputRect) const {
  323. // Recurse only into color input.
  324. if (this->getColorInput()) {
  325. return this->getColorInput()->filterBounds(src, ctm, dir, inputRect);
  326. }
  327. return src;
  328. }
  329. ///////////////////////////////////////////////////////////////////////////////
  330. #if SK_SUPPORT_GPU
  331. class GrGLDisplacementMapEffect : public GrGLSLFragmentProcessor {
  332. public:
  333. void emitCode(EmitArgs&) override;
  334. static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
  335. protected:
  336. void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
  337. private:
  338. typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
  339. UniformHandle fScaleUni;
  340. GrTextureDomain::GLDomain fGLDomain;
  341. typedef GrGLSLFragmentProcessor INHERITED;
  342. };
  343. ///////////////////////////////////////////////////////////////////////////////
  344. GrGLSLFragmentProcessor* GrDisplacementMapEffect::onCreateGLSLInstance() const {
  345. return new GrGLDisplacementMapEffect;
  346. }
  347. void GrDisplacementMapEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
  348. GrProcessorKeyBuilder* b) const {
  349. GrGLDisplacementMapEffect::GenKey(*this, caps, b);
  350. }
  351. GrDisplacementMapEffect::GrDisplacementMapEffect(
  352. SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
  353. SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
  354. const SkVector& scale,
  355. sk_sp<GrTextureProxy> displacement,
  356. const SkIRect& displSubset,
  357. const SkMatrix& offsetMatrix,
  358. sk_sp<GrTextureProxy> color,
  359. const SkIRect& colorSubset)
  360. : INHERITED(kGrDisplacementMapEffect_ClassID,
  361. GrFragmentProcessor::kNone_OptimizationFlags)
  362. , fDisplacementTransform(
  363. SkMatrix::Concat(SkMatrix::MakeTrans(displSubset.x(), displSubset.y()),
  364. offsetMatrix),
  365. displacement.get())
  366. , fDisplacementSampler(displacement)
  367. , fColorTransform(SkMatrix::MakeTrans(colorSubset.x(), colorSubset.y()), color.get())
  368. , fDomain(color.get(),
  369. GrTextureDomain::MakeTexelDomain(colorSubset,
  370. GrTextureDomain::kDecal_Mode),
  371. GrTextureDomain::kDecal_Mode, GrTextureDomain::kDecal_Mode)
  372. , fColorSampler(color)
  373. , fXChannelSelector(xChannelSelector)
  374. , fYChannelSelector(yChannelSelector)
  375. , fScale(scale) {
  376. this->addCoordTransform(&fDisplacementTransform);
  377. this->addCoordTransform(&fColorTransform);
  378. this->setTextureSamplerCnt(2);
  379. }
  380. GrDisplacementMapEffect::GrDisplacementMapEffect(const GrDisplacementMapEffect& that)
  381. : INHERITED(kGrDisplacementMapEffect_ClassID, that.optimizationFlags())
  382. , fDisplacementTransform(that.fDisplacementTransform)
  383. , fDisplacementSampler(that.fDisplacementSampler)
  384. , fColorTransform(that.fColorTransform)
  385. , fDomain(that.fDomain)
  386. , fColorSampler(that.fColorSampler)
  387. , fXChannelSelector(that.fXChannelSelector)
  388. , fYChannelSelector(that.fYChannelSelector)
  389. , fScale(that.fScale) {
  390. this->addCoordTransform(&fDisplacementTransform);
  391. this->addCoordTransform(&fColorTransform);
  392. this->setTextureSamplerCnt(2);
  393. }
  394. GrDisplacementMapEffect::~GrDisplacementMapEffect() {}
  395. std::unique_ptr<GrFragmentProcessor> GrDisplacementMapEffect::clone() const {
  396. return std::unique_ptr<GrFragmentProcessor>(new GrDisplacementMapEffect(*this));
  397. }
  398. bool GrDisplacementMapEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
  399. const GrDisplacementMapEffect& s = sBase.cast<GrDisplacementMapEffect>();
  400. return fXChannelSelector == s.fXChannelSelector &&
  401. fYChannelSelector == s.fYChannelSelector &&
  402. fScale == s.fScale;
  403. }
  404. ///////////////////////////////////////////////////////////////////////////////
  405. GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDisplacementMapEffect);
  406. #if GR_TEST_UTILS
  407. std::unique_ptr<GrFragmentProcessor> GrDisplacementMapEffect::TestCreate(GrProcessorTestData* d) {
  408. int texIdxDispl = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
  409. GrProcessorUnitTest::kAlphaTextureIdx;
  410. int texIdxColor = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
  411. GrProcessorUnitTest::kAlphaTextureIdx;
  412. sk_sp<GrTextureProxy> dispProxy = d->textureProxy(texIdxDispl);
  413. sk_sp<GrTextureProxy> colorProxy = d->textureProxy(texIdxColor);
  414. static const int kMaxComponent = 4;
  415. SkDisplacementMapEffect::ChannelSelectorType xChannelSelector =
  416. static_cast<SkDisplacementMapEffect::ChannelSelectorType>(
  417. d->fRandom->nextRangeU(1, kMaxComponent));
  418. SkDisplacementMapEffect::ChannelSelectorType yChannelSelector =
  419. static_cast<SkDisplacementMapEffect::ChannelSelectorType>(
  420. d->fRandom->nextRangeU(1, kMaxComponent));
  421. SkVector scale = SkVector::Make(d->fRandom->nextRangeScalar(0, 100.0f),
  422. d->fRandom->nextRangeScalar(0, 100.0f));
  423. SkISize colorDimensions;
  424. colorDimensions.fWidth = d->fRandom->nextRangeU(0, colorProxy->width());
  425. colorDimensions.fHeight = d->fRandom->nextRangeU(0, colorProxy->height());
  426. SkIRect dispRect = SkIRect::MakeWH(dispProxy->width(), dispProxy->height());
  427. return GrDisplacementMapEffect::Make(xChannelSelector, yChannelSelector, scale,
  428. std::move(dispProxy),
  429. dispRect,
  430. SkMatrix::I(),
  431. std::move(colorProxy), SkIRect::MakeSize(colorDimensions));
  432. }
  433. #endif
  434. ///////////////////////////////////////////////////////////////////////////////
  435. void GrGLDisplacementMapEffect::emitCode(EmitArgs& args) {
  436. const GrDisplacementMapEffect& displacementMap = args.fFp.cast<GrDisplacementMapEffect>();
  437. const GrTextureDomain& domain = displacementMap.domain();
  438. fScaleUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType, "Scale");
  439. const char* scaleUni = args.fUniformHandler->getUniformCStr(fScaleUni);
  440. const char* dColor = "dColor";
  441. const char* cCoords = "cCoords";
  442. const char* nearZero = "1e-6"; // Since 6.10352e-5 is the smallest half float, use
  443. // a number smaller than that to approximate 0, but
  444. // leave room for 32-bit float GPU rounding errors.
  445. GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
  446. fragBuilder->codeAppendf("\t\thalf4 %s = ", dColor);
  447. fragBuilder->appendTextureLookup(args.fTexSamplers[0], args.fTransformedCoords[0].c_str(),
  448. args.fTransformedCoords[0].getType());
  449. fragBuilder->codeAppend(";\n");
  450. // Unpremultiply the displacement
  451. fragBuilder->codeAppendf(
  452. "\t\t%s.rgb = (%s.a < %s) ? half3(0.0) : saturate(%s.rgb / %s.a);",
  453. dColor, dColor, nearZero, dColor, dColor);
  454. SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[1]);
  455. fragBuilder->codeAppendf("\t\tfloat2 %s = %s + %s*(%s.",
  456. cCoords, coords2D.c_str(), scaleUni, dColor);
  457. switch (displacementMap.xChannelSelector()) {
  458. case SkDisplacementMapEffect::kR_ChannelSelectorType:
  459. fragBuilder->codeAppend("r");
  460. break;
  461. case SkDisplacementMapEffect::kG_ChannelSelectorType:
  462. fragBuilder->codeAppend("g");
  463. break;
  464. case SkDisplacementMapEffect::kB_ChannelSelectorType:
  465. fragBuilder->codeAppend("b");
  466. break;
  467. case SkDisplacementMapEffect::kA_ChannelSelectorType:
  468. fragBuilder->codeAppend("a");
  469. break;
  470. case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
  471. default:
  472. SkDEBUGFAIL("Unknown X channel selector");
  473. }
  474. switch (displacementMap.yChannelSelector()) {
  475. case SkDisplacementMapEffect::kR_ChannelSelectorType:
  476. fragBuilder->codeAppend("r");
  477. break;
  478. case SkDisplacementMapEffect::kG_ChannelSelectorType:
  479. fragBuilder->codeAppend("g");
  480. break;
  481. case SkDisplacementMapEffect::kB_ChannelSelectorType:
  482. fragBuilder->codeAppend("b");
  483. break;
  484. case SkDisplacementMapEffect::kA_ChannelSelectorType:
  485. fragBuilder->codeAppend("a");
  486. break;
  487. case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
  488. default:
  489. SkDEBUGFAIL("Unknown Y channel selector");
  490. }
  491. fragBuilder->codeAppend("-half2(0.5));\t\t");
  492. fGLDomain.sampleTexture(fragBuilder,
  493. args.fUniformHandler,
  494. args.fShaderCaps,
  495. domain,
  496. args.fOutputColor,
  497. SkString(cCoords),
  498. args.fTexSamplers[1]);
  499. fragBuilder->codeAppend(";\n");
  500. }
  501. void GrGLDisplacementMapEffect::onSetData(const GrGLSLProgramDataManager& pdman,
  502. const GrFragmentProcessor& proc) {
  503. const GrDisplacementMapEffect& displacementMap = proc.cast<GrDisplacementMapEffect>();
  504. GrTextureProxy* proxy = displacementMap.textureSampler(1).proxy();
  505. GrTexture* colorTex = proxy->peekTexture();
  506. SkScalar scaleX = displacementMap.scale().fX / colorTex->width();
  507. SkScalar scaleY = displacementMap.scale().fY / colorTex->height();
  508. pdman.set2f(fScaleUni, SkScalarToFloat(scaleX),
  509. proxy->origin() == kTopLeft_GrSurfaceOrigin ?
  510. SkScalarToFloat(scaleY) : SkScalarToFloat(-scaleY));
  511. fGLDomain.setData(pdman, displacementMap.domain(), proxy,
  512. displacementMap.textureSampler(1).samplerState());
  513. }
  514. void GrGLDisplacementMapEffect::GenKey(const GrProcessor& proc,
  515. const GrShaderCaps&, GrProcessorKeyBuilder* b) {
  516. const GrDisplacementMapEffect& displacementMap = proc.cast<GrDisplacementMapEffect>();
  517. uint32_t xKey = displacementMap.xChannelSelector();
  518. uint32_t yKey = displacementMap.yChannelSelector() << kChannelSelectorKeyBits;
  519. b->add32(xKey | yKey);
  520. }
  521. #endif