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 "SkBitmapProcShader.h" 9 #include "SkColorShader.h" 10 #include "SkEmptyShader.h" 11 #include "SkReadBuffer.h" 12 #include "SkMallocPixelRef.h" 13 #include "SkPaint.h" 14 #include "SkPicture.h" 15 #include "SkPictureShader.h" 16 #include "SkScalar.h" 17 #include "SkShader.h" 18 #include "SkThread.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 } 48 49 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING 50 SkShader::SkShader(SkReadBuffer& buffer) : INHERITED(buffer) { 51 inc_shader_counter(); 52 if (buffer.readBool()) { 53 buffer.readMatrix(&fLocalMatrix); 54 } else { 55 fLocalMatrix.reset(); 56 } 57 } 58 #endif 59 60 SkShader::~SkShader() { 61 dec_shader_counter(); 62 } 63 64 void SkShader::flatten(SkWriteBuffer& buffer) const { 65 this->INHERITED::flatten(buffer); 66 bool hasLocalM = !fLocalMatrix.isIdentity(); 67 buffer.writeBool(hasLocalM); 68 if (hasLocalM) { 69 buffer.writeMatrix(fLocalMatrix); 70 } 71 } 72 73 bool SkShader::computeTotalInverse(const ContextRec& rec, SkMatrix* totalInverse) const { 74 SkMatrix total; 75 total.setConcat(*rec.fMatrix, fLocalMatrix); 76 77 const SkMatrix* m = &total; 78 if (rec.fLocalMatrix) { 79 total.setConcat(*m, *rec.fLocalMatrix); 80 m = &total; 81 } 82 return m->invert(totalInverse); 83 } 84 85 bool SkShader::asLuminanceColor(SkColor* colorPtr) const { 86 SkColor storage; 87 if (NULL == colorPtr) { 88 colorPtr = &storage; 89 } 90 if (this->onAsLuminanceColor(colorPtr)) { 91 *colorPtr = SkColorSetA(*colorPtr, 0xFF); // we only return opaque 92 return true; 93 } 94 return false; 95 } 96 97 SkShader::Context* SkShader::createContext(const ContextRec& rec, void* storage) const { 98 if (!this->computeTotalInverse(rec, NULL)) { 99 return NULL; 100 } 101 return this->onCreateContext(rec, storage); 102 } 103 104 SkShader::Context* SkShader::onCreateContext(const ContextRec& rec, void*) const { 105 return NULL; 106 } 107 108 size_t SkShader::contextSize() const { 109 return 0; 110 } 111 112 SkShader::Context::Context(const SkShader& shader, const ContextRec& rec) 113 : fShader(shader), fCTM(*rec.fMatrix) 114 { 115 // Because the context parameters must be valid at this point, we know that the matrix is 116 // invertible. 117 SkAssertResult(fShader.computeTotalInverse(rec, &fTotalInverse)); 118 fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse); 119 120 fPaintAlpha = rec.fPaint->getAlpha(); 121 } 122 123 SkShader::Context::~Context() {} 124 125 SkShader::Context::ShadeProc SkShader::Context::asAShadeProc(void** ctx) { 126 return NULL; 127 } 128 129 #include "SkColorPriv.h" 130 131 void SkShader::Context::shadeSpan16(int x, int y, uint16_t span16[], int count) { 132 SkASSERT(span16); 133 SkASSERT(count > 0); 134 SkASSERT(this->canCallShadeSpan16()); 135 136 // basically, if we get here, the subclass screwed up 137 SkDEBUGFAIL("kHasSpan16 flag is set, but shadeSpan16() not implemented"); 138 } 139 140 #define kTempColorQuadCount 6 // balance between speed (larger) and saving stack-space 141 #define kTempColorCount (kTempColorQuadCount << 2) 142 143 #ifdef SK_CPU_BENDIAN 144 #define SkU32BitShiftToByteOffset(shift) (3 - ((shift) >> 3)) 145 #else 146 #define SkU32BitShiftToByteOffset(shift) ((shift) >> 3) 147 #endif 148 149 void SkShader::Context::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { 150 SkASSERT(count > 0); 151 152 SkPMColor colors[kTempColorCount]; 153 154 while ((count -= kTempColorCount) >= 0) { 155 this->shadeSpan(x, y, colors, kTempColorCount); 156 x += kTempColorCount; 157 158 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); 159 int quads = kTempColorQuadCount; 160 do { 161 U8CPU a0 = srcA[0]; 162 U8CPU a1 = srcA[4]; 163 U8CPU a2 = srcA[8]; 164 U8CPU a3 = srcA[12]; 165 srcA += 4*4; 166 *alpha++ = SkToU8(a0); 167 *alpha++ = SkToU8(a1); 168 *alpha++ = SkToU8(a2); 169 *alpha++ = SkToU8(a3); 170 } while (--quads != 0); 171 } 172 SkASSERT(count < 0); 173 SkASSERT(count + kTempColorCount >= 0); 174 if (count += kTempColorCount) { 175 this->shadeSpan(x, y, colors, count); 176 177 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); 178 do { 179 *alpha++ = *srcA; 180 srcA += 4; 181 } while (--count != 0); 182 } 183 #if 0 184 do { 185 int n = count; 186 if (n > kTempColorCount) 187 n = kTempColorCount; 188 SkASSERT(n > 0); 189 190 this->shadeSpan(x, y, colors, n); 191 x += n; 192 count -= n; 193 194 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); 195 do { 196 *alpha++ = *srcA; 197 srcA += 4; 198 } while (--n != 0); 199 } while (count > 0); 200 #endif 201 } 202 203 SkShader::Context::MatrixClass SkShader::Context::ComputeMatrixClass(const SkMatrix& mat) { 204 MatrixClass mc = kLinear_MatrixClass; 205 206 if (mat.hasPerspective()) { 207 if (mat.fixedStepInX(0, NULL, NULL)) { 208 mc = kFixedStepInX_MatrixClass; 209 } else { 210 mc = kPerspective_MatrixClass; 211 } 212 } 213 return mc; 214 } 215 216 ////////////////////////////////////////////////////////////////////////////// 217 218 SkShader::BitmapType SkShader::asABitmap(SkBitmap*, SkMatrix*, TileMode*) const { 219 return kNone_BitmapType; 220 } 221 222 SkShader::GradientType SkShader::asAGradient(GradientInfo* info) const { 223 return kNone_GradientType; 224 } 225 226 bool SkShader::asFragmentProcessor(GrContext*, const SkPaint&, const SkMatrix*, GrColor*, 227 GrFragmentProcessor**) const { 228 return false; 229 } 230 231 SkShader* SkShader::refAsALocalMatrixShader(SkMatrix*) const { 232 return NULL; 233 } 234 235 SkShader* SkShader::CreateEmptyShader() { 236 return SkNEW(SkEmptyShader); 237 } 238 239 SkShader* SkShader::CreateColorShader(SkColor color) { 240 return SkNEW_ARGS(SkColorShader, (color)); 241 } 242 243 SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, TileMode tmx, TileMode tmy, 244 const SkMatrix* localMatrix) { 245 return ::CreateBitmapShader(src, tmx, tmy, localMatrix, NULL); 246 } 247 248 SkShader* SkShader::CreatePictureShader(SkPicture* src, TileMode tmx, TileMode tmy, 249 const SkMatrix* localMatrix, const SkRect* tile) { 250 return SkPictureShader::Create(src, tmx, tmy, localMatrix, tile); 251 } 252 253 #ifndef SK_IGNORE_TO_STRING 254 void SkShader::toString(SkString* str) const { 255 if (!fLocalMatrix.isIdentity()) { 256 str->append(" "); 257 fLocalMatrix.toString(str); 258 } 259 } 260 #endif 261 262 ////////////////////////////////////////////////////////////////////////////// 263 264 #include "SkUtils.h" 265 266 SkColorShader::SkColorShader(SkColor c) 267 : fColor(c) { 268 } 269 270 bool SkColorShader::isOpaque() const { 271 return SkColorGetA(fColor) == 255; 272 } 273 274 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING 275 SkColorShader::SkColorShader(SkReadBuffer& b) : INHERITED(b) { 276 // V25_COMPATIBILITY_CODE We had a boolean to make the color shader inherit the paint's 277 // color. We don't support that any more. 278 if (b.isVersionLT(SkReadBuffer::kColorShaderNoBool_Version)) { 279 if (b.readBool()) { 280 SkDEBUGFAIL("We shouldn't have pictures that recorded the inherited case."); 281 fColor = SK_ColorWHITE; 282 return; 283 } 284 } 285 fColor = b.readColor(); 286 } 287 #endif 288 289 SkFlattenable* SkColorShader::CreateProc(SkReadBuffer& buffer) { 290 return SkNEW_ARGS(SkColorShader, (buffer.readColor())); 291 } 292 293 void SkColorShader::flatten(SkWriteBuffer& buffer) const { 294 buffer.writeColor(fColor); 295 } 296 297 uint32_t SkColorShader::ColorShaderContext::getFlags() const { 298 return fFlags; 299 } 300 301 uint8_t SkColorShader::ColorShaderContext::getSpan16Alpha() const { 302 return SkGetPackedA32(fPMColor); 303 } 304 305 SkShader::Context* SkColorShader::onCreateContext(const ContextRec& rec, void* storage) const { 306 return SkNEW_PLACEMENT_ARGS(storage, ColorShaderContext, (*this, rec)); 307 } 308 309 SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shader, 310 const ContextRec& rec) 311 : INHERITED(shader, rec) 312 { 313 SkColor color = shader.fColor; 314 unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha())); 315 316 unsigned r = SkColorGetR(color); 317 unsigned g = SkColorGetG(color); 318 unsigned b = SkColorGetB(color); 319 320 // we want this before we apply any alpha 321 fColor16 = SkPack888ToRGB16(r, g, b); 322 323 if (a != 255) { 324 r = SkMulDiv255Round(r, a); 325 g = SkMulDiv255Round(g, a); 326 b = SkMulDiv255Round(b, a); 327 } 328 fPMColor = SkPackARGB32(a, r, g, b); 329 330 fFlags = kConstInY32_Flag; 331 if (255 == a) { 332 fFlags |= kOpaqueAlpha_Flag; 333 if (rec.fPaint->isDither() == false) { 334 fFlags |= kHasSpan16_Flag; 335 } 336 } 337 } 338 339 void SkColorShader::ColorShaderContext::shadeSpan(int x, int y, SkPMColor span[], int count) { 340 sk_memset32(span, fPMColor, count); 341 } 342 343 void SkColorShader::ColorShaderContext::shadeSpan16(int x, int y, uint16_t span[], int count) { 344 sk_memset16(span, fColor16, count); 345 } 346 347 void SkColorShader::ColorShaderContext::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { 348 memset(alpha, SkGetPackedA32(fPMColor), count); 349 } 350 351 // if we had a asAColor method, that would be more efficient... 352 SkShader::BitmapType SkColorShader::asABitmap(SkBitmap* bitmap, SkMatrix* matrix, 353 TileMode modes[]) const { 354 return kNone_BitmapType; 355 } 356 357 SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const { 358 if (info) { 359 if (info->fColors && info->fColorCount >= 1) { 360 info->fColors[0] = fColor; 361 } 362 info->fColorCount = 1; 363 info->fTileMode = SkShader::kRepeat_TileMode; 364 } 365 return kColor_GradientType; 366 } 367 368 #if SK_SUPPORT_GPU 369 370 #include "SkGr.h" 371 372 bool SkColorShader::asFragmentProcessor(GrContext*, const SkPaint& paint, const SkMatrix*, 373 GrColor* paintColor, GrFragmentProcessor** fp) const { 374 *fp = NULL; 375 SkColor skColor = fColor; 376 U8CPU newA = SkMulDiv255Round(SkColorGetA(fColor), paint.getAlpha()); 377 *paintColor = SkColor2GrColor(SkColorSetA(skColor, newA)); 378 return true; 379 } 380 381 #else 382 383 bool SkColorShader::asFragmentProcessor(GrContext*, const SkPaint&, const SkMatrix*, GrColor*, 384 GrFragmentProcessor**) const { 385 SkDEBUGFAIL("Should not call in GPU-less build"); 386 return false; 387 } 388 389 #endif 390 391 #ifndef SK_IGNORE_TO_STRING 392 void SkColorShader::toString(SkString* str) const { 393 str->append("SkColorShader: ("); 394 395 str->append("Color: "); 396 str->appendHex(fColor); 397 398 this->INHERITED::toString(str); 399 400 str->append(")"); 401 } 402 #endif 403 404 /////////////////////////////////////////////////////////////////////////////// 405 406 SkFlattenable* SkEmptyShader::CreateProc(SkReadBuffer&) { 407 return SkShader::CreateEmptyShader(); 408 } 409 410 #ifndef SK_IGNORE_TO_STRING 411 #include "SkEmptyShader.h" 412 413 void SkEmptyShader::toString(SkString* str) const { 414 str->append("SkEmptyShader: ("); 415 416 this->INHERITED::toString(str); 417 418 str->append(")"); 419 } 420 #endif 421