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 8 #include "SkAtomics.h" 9 #include "SkBitmapProcShader.h" 10 #include "SkColorShader.h" 11 #include "SkEmptyShader.h" 12 #include "SkMallocPixelRef.h" 13 #include "SkPaint.h" 14 #include "SkPicture.h" 15 #include "SkPictureShader.h" 16 #include "SkReadBuffer.h" 17 #include "SkScalar.h" 18 #include "SkShader.h" 19 #include "SkWriteBuffer.h" 20 21 //#define SK_TRACK_SHADER_LIFETIME 22 23 #ifdef SK_TRACK_SHADER_LIFETIME 24 static int32_t gShaderCounter; 25 #endif 26 27 static inline void inc_shader_counter() { 28 #ifdef SK_TRACK_SHADER_LIFETIME 29 int32_t prev = sk_atomic_inc(&gShaderCounter); 30 SkDebugf("+++ shader counter %d\n", prev + 1); 31 #endif 32 } 33 static inline void dec_shader_counter() { 34 #ifdef SK_TRACK_SHADER_LIFETIME 35 int32_t prev = sk_atomic_dec(&gShaderCounter); 36 SkDebugf("--- shader counter %d\n", prev - 1); 37 #endif 38 } 39 40 SkShader::SkShader(const SkMatrix* localMatrix) { 41 inc_shader_counter(); 42 if (localMatrix) { 43 fLocalMatrix = *localMatrix; 44 } else { 45 fLocalMatrix.reset(); 46 } 47 // Pre-cache so future calls to fLocalMatrix.getType() are threadsafe. 48 (void)fLocalMatrix.getType(); 49 } 50 51 SkShader::~SkShader() { 52 dec_shader_counter(); 53 } 54 55 void SkShader::flatten(SkWriteBuffer& buffer) const { 56 this->INHERITED::flatten(buffer); 57 bool hasLocalM = !fLocalMatrix.isIdentity(); 58 buffer.writeBool(hasLocalM); 59 if (hasLocalM) { 60 buffer.writeMatrix(fLocalMatrix); 61 } 62 } 63 64 bool SkShader::computeTotalInverse(const ContextRec& rec, SkMatrix* totalInverse) const { 65 SkMatrix total; 66 total.setConcat(*rec.fMatrix, fLocalMatrix); 67 68 const SkMatrix* m = &total; 69 if (rec.fLocalMatrix) { 70 total.setConcat(*m, *rec.fLocalMatrix); 71 m = &total; 72 } 73 return m->invert(totalInverse); 74 } 75 76 bool SkShader::asLuminanceColor(SkColor* colorPtr) const { 77 SkColor storage; 78 if (nullptr == colorPtr) { 79 colorPtr = &storage; 80 } 81 if (this->onAsLuminanceColor(colorPtr)) { 82 *colorPtr = SkColorSetA(*colorPtr, 0xFF); // we only return opaque 83 return true; 84 } 85 return false; 86 } 87 88 SkShader::Context* SkShader::createContext(const ContextRec& rec, void* storage) const { 89 if (!this->computeTotalInverse(rec, nullptr)) { 90 return nullptr; 91 } 92 return this->onCreateContext(rec, storage); 93 } 94 95 SkShader::Context* SkShader::onCreateContext(const ContextRec& rec, void*) const { 96 return nullptr; 97 } 98 99 size_t SkShader::contextSize(const ContextRec&) const { 100 return 0; 101 } 102 103 SkShader::Context::Context(const SkShader& shader, const ContextRec& rec) 104 : fShader(shader), fCTM(*rec.fMatrix) 105 { 106 // Because the context parameters must be valid at this point, we know that the matrix is 107 // invertible. 108 SkAssertResult(fShader.computeTotalInverse(rec, &fTotalInverse)); 109 fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse); 110 111 fPaintAlpha = rec.fPaint->getAlpha(); 112 } 113 114 SkShader::Context::~Context() {} 115 116 SkShader::Context::ShadeProc SkShader::Context::asAShadeProc(void** ctx) { 117 return nullptr; 118 } 119 120 void SkShader::Context::shadeSpan4f(int x, int y, SkPM4f dst[], int count) { 121 const int N = 128; 122 SkPMColor tmp[N]; 123 while (count > 0) { 124 int n = SkTMin(count, N); 125 this->shadeSpan(x, y, tmp, n); 126 for (int i = 0; i < n; ++i) { 127 dst[i] = SkPM4f::FromPMColor(tmp[i]); 128 } 129 dst += n; 130 x += n; 131 count -= n; 132 } 133 } 134 135 #include "SkColorPriv.h" 136 137 #define kTempColorQuadCount 6 // balance between speed (larger) and saving stack-space 138 #define kTempColorCount (kTempColorQuadCount << 2) 139 140 #ifdef SK_CPU_BENDIAN 141 #define SkU32BitShiftToByteOffset(shift) (3 - ((shift) >> 3)) 142 #else 143 #define SkU32BitShiftToByteOffset(shift) ((shift) >> 3) 144 #endif 145 146 void SkShader::Context::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { 147 SkASSERT(count > 0); 148 149 SkPMColor colors[kTempColorCount]; 150 151 while ((count -= kTempColorCount) >= 0) { 152 this->shadeSpan(x, y, colors, kTempColorCount); 153 x += kTempColorCount; 154 155 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); 156 int quads = kTempColorQuadCount; 157 do { 158 U8CPU a0 = srcA[0]; 159 U8CPU a1 = srcA[4]; 160 U8CPU a2 = srcA[8]; 161 U8CPU a3 = srcA[12]; 162 srcA += 4*4; 163 *alpha++ = SkToU8(a0); 164 *alpha++ = SkToU8(a1); 165 *alpha++ = SkToU8(a2); 166 *alpha++ = SkToU8(a3); 167 } while (--quads != 0); 168 } 169 SkASSERT(count < 0); 170 SkASSERT(count + kTempColorCount >= 0); 171 if (count += kTempColorCount) { 172 this->shadeSpan(x, y, colors, count); 173 174 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); 175 do { 176 *alpha++ = *srcA; 177 srcA += 4; 178 } while (--count != 0); 179 } 180 #if 0 181 do { 182 int n = count; 183 if (n > kTempColorCount) 184 n = kTempColorCount; 185 SkASSERT(n > 0); 186 187 this->shadeSpan(x, y, colors, n); 188 x += n; 189 count -= n; 190 191 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); 192 do { 193 *alpha++ = *srcA; 194 srcA += 4; 195 } while (--n != 0); 196 } while (count > 0); 197 #endif 198 } 199 200 SkShader::Context::MatrixClass SkShader::Context::ComputeMatrixClass(const SkMatrix& mat) { 201 MatrixClass mc = kLinear_MatrixClass; 202 203 if (mat.hasPerspective()) { 204 if (mat.isFixedStepInX()) { 205 mc = kFixedStepInX_MatrixClass; 206 } else { 207 mc = kPerspective_MatrixClass; 208 } 209 } 210 return mc; 211 } 212 213 ////////////////////////////////////////////////////////////////////////////// 214 215 SkShader::GradientType SkShader::asAGradient(GradientInfo* info) const { 216 return kNone_GradientType; 217 } 218 219 const GrFragmentProcessor* SkShader::asFragmentProcessor(GrContext*, const SkMatrix&, 220 const SkMatrix*, SkFilterQuality) const { 221 return nullptr; 222 } 223 224 SkShader* SkShader::refAsALocalMatrixShader(SkMatrix*) const { 225 return nullptr; 226 } 227 228 SkShader* SkShader::CreateEmptyShader() { return new SkEmptyShader; } 229 230 SkShader* SkShader::CreateColorShader(SkColor color) { return new SkColorShader(color); } 231 232 SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, TileMode tmx, TileMode tmy, 233 const SkMatrix* localMatrix) { 234 return SkCreateBitmapShader(src, tmx, tmy, localMatrix, nullptr); 235 } 236 237 SkShader* SkShader::CreatePictureShader(const SkPicture* src, TileMode tmx, TileMode tmy, 238 const SkMatrix* localMatrix, const SkRect* tile) { 239 return SkPictureShader::Create(src, tmx, tmy, localMatrix, tile); 240 } 241 242 #ifndef SK_IGNORE_TO_STRING 243 void SkShader::toString(SkString* str) const { 244 if (!fLocalMatrix.isIdentity()) { 245 str->append(" "); 246 fLocalMatrix.toString(str); 247 } 248 } 249 #endif 250 251 ////////////////////////////////////////////////////////////////////////////// 252 253 #include "SkUtils.h" 254 255 SkColorShader::SkColorShader(SkColor c) 256 : fColor(c) { 257 } 258 259 bool SkColorShader::isOpaque() const { 260 return SkColorGetA(fColor) == 255; 261 } 262 263 SkFlattenable* SkColorShader::CreateProc(SkReadBuffer& buffer) { 264 return new SkColorShader(buffer.readColor()); 265 } 266 267 void SkColorShader::flatten(SkWriteBuffer& buffer) const { 268 buffer.writeColor(fColor); 269 } 270 271 uint32_t SkColorShader::ColorShaderContext::getFlags() const { 272 return fFlags; 273 } 274 275 SkShader::Context* SkColorShader::onCreateContext(const ContextRec& rec, void* storage) const { 276 return new (storage) ColorShaderContext(*this, rec); 277 } 278 279 SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shader, 280 const ContextRec& rec) 281 : INHERITED(shader, rec) 282 { 283 SkColor color = shader.fColor; 284 unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha())); 285 286 unsigned r = SkColorGetR(color); 287 unsigned g = SkColorGetG(color); 288 unsigned b = SkColorGetB(color); 289 290 if (a != 255) { 291 r = SkMulDiv255Round(r, a); 292 g = SkMulDiv255Round(g, a); 293 b = SkMulDiv255Round(b, a); 294 } 295 fPMColor = SkPackARGB32(a, r, g, b); 296 297 SkColor4f c4 = SkColor4f::FromColor(shader.fColor); 298 c4.fA *= rec.fPaint->getAlpha() / 255.0f; 299 fPM4f = c4.premul(); 300 301 fFlags = kConstInY32_Flag; 302 if (255 == a) { 303 fFlags |= kOpaqueAlpha_Flag; 304 } 305 } 306 307 void SkColorShader::ColorShaderContext::shadeSpan(int x, int y, SkPMColor span[], int count) { 308 sk_memset32(span, fPMColor, count); 309 } 310 311 void SkColorShader::ColorShaderContext::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { 312 memset(alpha, SkGetPackedA32(fPMColor), count); 313 } 314 315 void SkColorShader::ColorShaderContext::shadeSpan4f(int x, int y, SkPM4f span[], int count) { 316 for (int i = 0; i < count; ++i) { 317 span[i] = fPM4f; 318 } 319 } 320 321 SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const { 322 if (info) { 323 if (info->fColors && info->fColorCount >= 1) { 324 info->fColors[0] = fColor; 325 } 326 info->fColorCount = 1; 327 info->fTileMode = SkShader::kRepeat_TileMode; 328 } 329 return kColor_GradientType; 330 } 331 332 #if SK_SUPPORT_GPU 333 334 #include "SkGr.h" 335 #include "effects/GrConstColorProcessor.h" 336 const GrFragmentProcessor* SkColorShader::asFragmentProcessor(GrContext*, const SkMatrix&, 337 const SkMatrix*, 338 SkFilterQuality) const { 339 GrColor color = SkColorToPremulGrColor(fColor); 340 return GrConstColorProcessor::Create(color, GrConstColorProcessor::kModulateA_InputMode); 341 } 342 343 #endif 344 345 #ifndef SK_IGNORE_TO_STRING 346 void SkColorShader::toString(SkString* str) const { 347 str->append("SkColorShader: ("); 348 349 str->append("Color: "); 350 str->appendHex(fColor); 351 352 this->INHERITED::toString(str); 353 354 str->append(")"); 355 } 356 #endif 357 358 /////////////////////////////////////////////////////////////////////////////// 359 360 SkFlattenable* SkEmptyShader::CreateProc(SkReadBuffer&) { 361 return SkShader::CreateEmptyShader(); 362 } 363 364 #ifndef SK_IGNORE_TO_STRING 365 #include "SkEmptyShader.h" 366 367 void SkEmptyShader::toString(SkString* str) const { 368 str->append("SkEmptyShader: ("); 369 370 this->INHERITED::toString(str); 371 372 str->append(")"); 373 } 374 #endif 375