SkShader.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /*
  2. * Copyright 2006 The Android Open Source Project
  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/core/SkMallocPixelRef.h"
  8. #include "include/core/SkPaint.h"
  9. #include "include/core/SkPicture.h"
  10. #include "include/core/SkScalar.h"
  11. #include "src/core/SkArenaAlloc.h"
  12. #include "src/core/SkColorSpacePriv.h"
  13. #include "src/core/SkColorSpaceXformSteps.h"
  14. #include "src/core/SkRasterPipeline.h"
  15. #include "src/core/SkReadBuffer.h"
  16. #include "src/core/SkTLazy.h"
  17. #include "src/core/SkWriteBuffer.h"
  18. #include "src/shaders/SkBitmapProcShader.h"
  19. #include "src/shaders/SkColorShader.h"
  20. #include "src/shaders/SkEmptyShader.h"
  21. #include "src/shaders/SkPictureShader.h"
  22. #include "src/shaders/SkShaderBase.h"
  23. #if SK_SUPPORT_GPU
  24. #include "src/gpu/GrFragmentProcessor.h"
  25. #endif
  26. SkShaderBase::SkShaderBase(const SkMatrix* localMatrix)
  27. : fLocalMatrix(localMatrix ? *localMatrix : SkMatrix::I()) {
  28. // Pre-cache so future calls to fLocalMatrix.getType() are threadsafe.
  29. (void)fLocalMatrix.getType();
  30. }
  31. SkShaderBase::~SkShaderBase() {}
  32. void SkShaderBase::flatten(SkWriteBuffer& buffer) const {
  33. this->INHERITED::flatten(buffer);
  34. bool hasLocalM = !fLocalMatrix.isIdentity();
  35. buffer.writeBool(hasLocalM);
  36. if (hasLocalM) {
  37. buffer.writeMatrix(fLocalMatrix);
  38. }
  39. }
  40. SkTCopyOnFirstWrite<SkMatrix>
  41. SkShaderBase::totalLocalMatrix(const SkMatrix* preLocalMatrix,
  42. const SkMatrix* postLocalMatrix) const {
  43. SkTCopyOnFirstWrite<SkMatrix> m(fLocalMatrix);
  44. if (preLocalMatrix) {
  45. m.writable()->preConcat(*preLocalMatrix);
  46. }
  47. if (postLocalMatrix) {
  48. m.writable()->postConcat(*postLocalMatrix);
  49. }
  50. return m;
  51. }
  52. bool SkShaderBase::computeTotalInverse(const SkMatrix& ctm,
  53. const SkMatrix* outerLocalMatrix,
  54. SkMatrix* totalInverse) const {
  55. return SkMatrix::Concat(ctm, *this->totalLocalMatrix(outerLocalMatrix)).invert(totalInverse);
  56. }
  57. bool SkShaderBase::asLuminanceColor(SkColor* colorPtr) const {
  58. SkColor storage;
  59. if (nullptr == colorPtr) {
  60. colorPtr = &storage;
  61. }
  62. if (this->onAsLuminanceColor(colorPtr)) {
  63. *colorPtr = SkColorSetA(*colorPtr, 0xFF); // we only return opaque
  64. return true;
  65. }
  66. return false;
  67. }
  68. SkShaderBase::Context* SkShaderBase::makeContext(const ContextRec& rec, SkArenaAlloc* alloc) const {
  69. #ifdef SK_ENABLE_LEGACY_SHADERCONTEXT
  70. // We always fall back to raster pipeline when perspective is present.
  71. if (rec.fMatrix->hasPerspective() ||
  72. fLocalMatrix.hasPerspective() ||
  73. (rec.fLocalMatrix && rec.fLocalMatrix->hasPerspective()) ||
  74. !this->computeTotalInverse(*rec.fMatrix, rec.fLocalMatrix, nullptr)) {
  75. return nullptr;
  76. }
  77. return this->onMakeContext(rec, alloc);
  78. #else
  79. return nullptr;
  80. #endif
  81. }
  82. SkShaderBase::Context::Context(const SkShaderBase& shader, const ContextRec& rec)
  83. : fShader(shader), fCTM(*rec.fMatrix)
  84. {
  85. // We should never use a context with perspective.
  86. SkASSERT(!rec.fMatrix->hasPerspective());
  87. SkASSERT(!rec.fLocalMatrix || !rec.fLocalMatrix->hasPerspective());
  88. SkASSERT(!shader.getLocalMatrix().hasPerspective());
  89. // Because the context parameters must be valid at this point, we know that the matrix is
  90. // invertible.
  91. SkAssertResult(fShader.computeTotalInverse(*rec.fMatrix, rec.fLocalMatrix, &fTotalInverse));
  92. fPaintAlpha = rec.fPaint->getAlpha();
  93. }
  94. SkShaderBase::Context::~Context() {}
  95. bool SkShaderBase::ContextRec::isLegacyCompatible(SkColorSpace* shaderColorSpace) const {
  96. return !SkColorSpaceXformSteps::Required(shaderColorSpace, fDstColorSpace);
  97. }
  98. SkImage* SkShader::isAImage(SkMatrix* localMatrix, SkTileMode xy[2]) const {
  99. return as_SB(this)->onIsAImage(localMatrix, xy);
  100. }
  101. SkShader::GradientType SkShader::asAGradient(GradientInfo* info) const {
  102. return kNone_GradientType;
  103. }
  104. #if SK_SUPPORT_GPU
  105. std::unique_ptr<GrFragmentProcessor> SkShaderBase::asFragmentProcessor(const GrFPArgs&) const {
  106. return nullptr;
  107. }
  108. #endif
  109. sk_sp<SkShader> SkShaderBase::makeAsALocalMatrixShader(SkMatrix*) const {
  110. return nullptr;
  111. }
  112. sk_sp<SkShader> SkShaders::Empty() { return sk_make_sp<SkEmptyShader>(); }
  113. sk_sp<SkShader> SkShaders::Color(SkColor color) { return sk_make_sp<SkColorShader>(color); }
  114. sk_sp<SkShader> SkBitmap::makeShader(SkTileMode tmx, SkTileMode tmy, const SkMatrix* lm) const {
  115. if (lm && !lm->invert(nullptr)) {
  116. return nullptr;
  117. }
  118. return SkMakeBitmapShader(*this, tmx, tmy, lm, kIfMutable_SkCopyPixelsMode);
  119. }
  120. sk_sp<SkShader> SkBitmap::makeShader(const SkMatrix* lm) const {
  121. return this->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, lm);
  122. }
  123. bool SkShaderBase::appendStages(const SkStageRec& rec) const {
  124. return this->onAppendStages(rec);
  125. }
  126. bool SkShaderBase::onAppendStages(const SkStageRec& rec) const {
  127. // SkShader::Context::shadeSpan() handles the paint opacity internally,
  128. // but SkRasterPipelineBlitter applies it as a separate stage.
  129. // We skip the internal shadeSpan() step by forcing the paint opaque.
  130. SkTCopyOnFirstWrite<SkPaint> opaquePaint(rec.fPaint);
  131. if (rec.fPaint.getAlpha() != SK_AlphaOPAQUE) {
  132. opaquePaint.writable()->setAlpha(SK_AlphaOPAQUE);
  133. }
  134. ContextRec cr(*opaquePaint, rec.fCTM, rec.fLocalM, rec.fDstColorType, sk_srgb_singleton());
  135. struct CallbackCtx : SkRasterPipeline_CallbackCtx {
  136. sk_sp<const SkShader> shader;
  137. Context* ctx;
  138. };
  139. auto cb = rec.fAlloc->make<CallbackCtx>();
  140. cb->shader = sk_ref_sp(this);
  141. cb->ctx = as_SB(this)->makeContext(cr, rec.fAlloc);
  142. cb->fn = [](SkRasterPipeline_CallbackCtx* self, int active_pixels) {
  143. auto c = (CallbackCtx*)self;
  144. int x = (int)c->rgba[0],
  145. y = (int)c->rgba[1];
  146. SkPMColor tmp[SkRasterPipeline_kMaxStride];
  147. c->ctx->shadeSpan(x,y, tmp, active_pixels);
  148. for (int i = 0; i < active_pixels; i++) {
  149. auto rgba_4f = SkPMColor4f::FromPMColor(tmp[i]);
  150. memcpy(c->rgba + 4*i, rgba_4f.vec(), 4*sizeof(float));
  151. }
  152. };
  153. if (cb->ctx) {
  154. rec.fPipeline->append(SkRasterPipeline::seed_shader);
  155. rec.fPipeline->append(SkRasterPipeline::callback, cb);
  156. rec.fAlloc->make<SkColorSpaceXformSteps>(sk_srgb_singleton(), kPremul_SkAlphaType,
  157. rec.fDstCS, kPremul_SkAlphaType)
  158. ->apply(rec.fPipeline, true);
  159. return true;
  160. }
  161. return false;
  162. }
  163. ///////////////////////////////////////////////////////////////////////////////////////////////////
  164. sk_sp<SkFlattenable> SkEmptyShader::CreateProc(SkReadBuffer&) {
  165. return SkShaders::Empty();
  166. }