OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkBitmapProcShader.h" | 8 #include "SkBitmapProcShader.h" |
9 #include "SkBitmapProcState.h" | 9 #include "SkBitmapProcState.h" |
10 #include "SkBitmapProvider.h" | 10 #include "SkBitmapProvider.h" |
11 #include "SkColorPriv.h" | |
12 #include "SkErrorInternals.h" | |
13 #include "SkPixelRef.h" | |
14 #include "SkReadBuffer.h" | |
15 #include "SkWriteBuffer.h" | |
16 | |
17 #if SK_SUPPORT_GPU | |
18 #include "SkGrPriv.h" | |
19 #include "effects/GrBicubicEffect.h" | |
20 #include "effects/GrSimpleTextureEffect.h" | |
21 #endif | |
22 | 11 |
23 static bool only_scale_and_translate(const SkMatrix& matrix) { | 12 static bool only_scale_and_translate(const SkMatrix& matrix) { |
24 unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; | 13 unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; |
25 return (matrix.getType() & ~mask) == 0; | 14 return (matrix.getType() & ~mask) == 0; |
26 } | 15 } |
27 | 16 |
28 class BitmapProcInfoContext : public SkShader::Context { | 17 class BitmapProcInfoContext : public SkShader::Context { |
29 public: | 18 public: |
30 // The info has been allocated elsewhere, but we are responsible for calling its destructor. | 19 // The info has been allocated elsewhere, but we are responsible for calling its destructor. |
31 BitmapProcInfoContext(const SkShader& shader, const SkShader::ContextRec& re c, | 20 BitmapProcInfoContext(const SkShader& shader, const SkShader::ContextRec& re c, |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
204 | 193 |
205 static bool choose_linear_pipeline(const SkShader::ContextRec& rec, const SkImag eInfo& srcInfo) { | 194 static bool choose_linear_pipeline(const SkShader::ContextRec& rec, const SkImag eInfo& srcInfo) { |
206 // If we get here, we can reasonably use either context, respect the caller' s preference | 195 // If we get here, we can reasonably use either context, respect the caller' s preference |
207 // | 196 // |
208 bool needsPremul = srcInfo.alphaType() == kUnpremul_SkAlphaType; | 197 bool needsPremul = srcInfo.alphaType() == kUnpremul_SkAlphaType; |
209 bool needsSwizzle = srcInfo.bytesPerPixel() == 4 && srcInfo.colorType() != k N32_SkColorType; | 198 bool needsSwizzle = srcInfo.bytesPerPixel() == 4 && srcInfo.colorType() != k N32_SkColorType; |
210 return SkShader::ContextRec::kPM4f_DstType == rec.fPreferredDstType | 199 return SkShader::ContextRec::kPM4f_DstType == rec.fPreferredDstType |
211 || needsPremul || needsSwizzle; | 200 || needsPremul || needsSwizzle; |
212 } | 201 } |
213 | 202 |
214 size_t SkBitmapProcShader::ContextSize(const ContextRec& rec, const SkImageInfo& srcInfo) { | 203 size_t SkBitmapProcLegacyShader::ContextSize(const ContextRec& rec, const SkImag eInfo& srcInfo) { |
215 size_t size0 = sizeof(BitmapProcShaderContext) + sizeof(SkBitmapProcState); | 204 size_t size0 = sizeof(BitmapProcShaderContext) + sizeof(SkBitmapProcState); |
216 size_t size1 = sizeof(LinearPipelineContext) + sizeof(SkBitmapProcInfo); | 205 size_t size1 = sizeof(LinearPipelineContext) + sizeof(SkBitmapProcInfo); |
206 size_t s = SkTMax(size0, size1); | |
207 return s; | |
scroggo
2016/09/08 13:42:24
This is effectively the same as the old code, righ
| |
217 return SkTMax(size0, size1); | 208 return SkTMax(size0, size1); |
218 } | 209 } |
219 | 210 |
220 SkShader::Context* SkBitmapProcShader::MakeContext(const SkShader& shader, | 211 SkShader::Context* SkBitmapProcLegacyShader::MakeContext(const SkShader& shader, |
221 TileMode tmx, TileMode tmy, | 212 TileMode tmx, TileMode tmy, |
222 const SkBitmapProvider& provi der, | 213 const SkBitmapProvider& provi der, |
223 const ContextRec& rec, void* storage) { | 214 const ContextRec& rec, void* storage) { |
224 SkMatrix totalInverse; | 215 SkMatrix totalInverse; |
225 // Do this first, so we know the matrix can be inverted. | 216 // Do this first, so we know the matrix can be inverted. |
226 if (!shader.computeTotalInverse(rec, &totalInverse)) { | 217 if (!shader.computeTotalInverse(rec, &totalInverse)) { |
227 return nullptr; | 218 return nullptr; |
228 } | 219 } |
229 | 220 |
230 // Decide if we can/want to use the new linear pipeline | 221 // Decide if we can/want to use the new linear pipeline |
(...skipping 13 matching lines...) Expand all Loading... | |
244 void* stateStorage = (char*)storage + sizeof(BitmapProcShaderContext); | 235 void* stateStorage = (char*)storage + sizeof(BitmapProcShaderContext); |
245 SkBitmapProcState* state = new (stateStorage) SkBitmapProcState(provider , tmx, tmy, | 236 SkBitmapProcState* state = new (stateStorage) SkBitmapProcState(provider , tmx, tmy, |
246 treatmen t); | 237 treatmen t); |
247 if (!state->setup(totalInverse, *rec.fPaint)) { | 238 if (!state->setup(totalInverse, *rec.fPaint)) { |
248 state->~SkBitmapProcState(); | 239 state->~SkBitmapProcState(); |
249 return nullptr; | 240 return nullptr; |
250 } | 241 } |
251 return new (storage) BitmapProcShaderContext(shader, rec, state); | 242 return new (storage) BitmapProcShaderContext(shader, rec, state); |
252 } | 243 } |
253 } | 244 } |
254 | |
255 SkShader::Context* SkBitmapProcShader::onCreateContext(const ContextRec& rec, vo id* storage) const { | |
256 return MakeContext(*this, (TileMode)fTileModeX, (TileMode)fTileModeY, | |
257 SkBitmapProvider(fRawBitmap), rec, storage); | |
258 } | |
259 | |
260 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
261 | |
262 SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src, TileMode tmx, TileMo de tmy, | |
263 const SkMatrix* localMatrix) | |
264 : INHERITED(localMatrix) { | |
265 fRawBitmap = src; | |
266 fTileModeX = (uint8_t)tmx; | |
267 fTileModeY = (uint8_t)tmy; | |
268 } | |
269 | |
270 bool SkBitmapProcShader::onIsABitmap(SkBitmap* texture, SkMatrix* texM, TileMode xy[]) const { | |
271 if (texture) { | |
272 *texture = fRawBitmap; | |
273 } | |
274 if (texM) { | |
275 *texM = this->getLocalMatrix(); | |
276 } | |
277 if (xy) { | |
278 xy[0] = (TileMode)fTileModeX; | |
279 xy[1] = (TileMode)fTileModeY; | |
280 } | |
281 return true; | |
282 } | |
283 | |
284 sk_sp<SkFlattenable> SkBitmapProcShader::CreateProc(SkReadBuffer& buffer) { | |
285 SkMatrix lm; | |
286 buffer.readMatrix(&lm); | |
287 SkBitmap bm; | |
288 if (!buffer.readBitmap(&bm)) { | |
289 return nullptr; | |
290 } | |
291 bm.setImmutable(); | |
292 TileMode mx = (TileMode)buffer.readUInt(); | |
293 TileMode my = (TileMode)buffer.readUInt(); | |
294 return SkShader::MakeBitmapShader(bm, mx, my, &lm); | |
295 } | |
296 | |
297 void SkBitmapProcShader::flatten(SkWriteBuffer& buffer) const { | |
298 buffer.writeMatrix(this->getLocalMatrix()); | |
299 buffer.writeBitmap(fRawBitmap); | |
300 buffer.writeUInt(fTileModeX); | |
301 buffer.writeUInt(fTileModeY); | |
302 } | |
303 | |
304 bool SkBitmapProcShader::isOpaque() const { | |
305 return fRawBitmap.isOpaque(); | |
306 } | |
307 | |
308 bool SkBitmapProcShader::BitmapIsTooBig(const SkBitmap& bm) { | |
309 static const int kMaxSize = 65535; | |
310 | |
311 return bm.width() > kMaxSize || bm.height() > kMaxSize; | |
312 } | |
313 | |
314 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
315 | |
316 #include "SkUnPreMultiply.h" | |
317 #include "SkColorShader.h" | |
318 #include "SkEmptyShader.h" | |
319 | |
320 // returns true and set color if the bitmap can be drawn as a single color | |
321 // (for efficiency) | |
322 static bool can_use_color_shader(const SkBitmap& bm, SkColor* color) { | |
323 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK | |
324 // HWUI does not support color shaders (see b/22390304) | |
325 return false; | |
326 #endif | |
327 | |
328 if (1 != bm.width() || 1 != bm.height()) { | |
329 return false; | |
330 } | |
331 | |
332 SkAutoLockPixels alp(bm); | |
333 if (!bm.readyToDraw()) { | |
334 return false; | |
335 } | |
336 | |
337 switch (bm.colorType()) { | |
338 case kN32_SkColorType: | |
339 *color = SkUnPreMultiply::PMColorToColor(*bm.getAddr32(0, 0)); | |
340 return true; | |
341 case kRGB_565_SkColorType: | |
342 *color = SkPixel16ToColor(*bm.getAddr16(0, 0)); | |
343 return true; | |
344 case kIndex_8_SkColorType: | |
345 *color = SkUnPreMultiply::PMColorToColor(bm.getIndex8Color(0, 0)); | |
346 return true; | |
347 default: // just skip the other configs for now | |
348 break; | |
349 } | |
350 return false; | |
351 } | |
352 | |
353 static bool bitmap_is_too_big(const SkBitmap& bm) { | |
354 // SkBitmapProcShader stores bitmap coordinates in a 16bit buffer, as it | |
355 // communicates between its matrix-proc and its sampler-proc. Until we can | |
356 // widen that, we have to reject bitmaps that are larger. | |
357 // | |
358 static const int kMaxSize = 65535; | |
359 | |
360 return bm.width() > kMaxSize || bm.height() > kMaxSize; | |
361 } | |
362 | |
363 sk_sp<SkShader> SkMakeBitmapShader(const SkBitmap& src, SkShader::TileMode tmx, | |
364 SkShader::TileMode tmy, const SkMatrix* local Matrix, | |
365 SkTBlitterAllocator* allocator) { | |
366 SkShader* shader; | |
367 SkColor color; | |
368 if (src.isNull() || bitmap_is_too_big(src)) { | |
369 if (nullptr == allocator) { | |
370 shader = new SkEmptyShader; | |
371 } else { | |
372 shader = allocator->createT<SkEmptyShader>(); | |
373 } | |
374 } else if (can_use_color_shader(src, &color)) { | |
375 if (nullptr == allocator) { | |
376 shader = new SkColorShader(color); | |
377 } else { | |
378 shader = allocator->createT<SkColorShader>(color); | |
379 } | |
380 } else { | |
381 if (nullptr == allocator) { | |
382 shader = new SkBitmapProcShader(src, tmx, tmy, localMatrix); | |
383 } else { | |
384 shader = allocator->createT<SkBitmapProcShader>(src, tmx, tmy, local Matrix); | |
385 } | |
386 } | |
387 return sk_sp<SkShader>(shader); | |
388 } | |
389 | |
390 /////////////////////////////////////////////////////////////////////////////// | |
391 | |
392 #ifndef SK_IGNORE_TO_STRING | |
393 void SkBitmapProcShader::toString(SkString* str) const { | |
394 static const char* gTileModeName[SkShader::kTileModeCount] = { | |
395 "clamp", "repeat", "mirror" | |
396 }; | |
397 | |
398 str->append("BitmapShader: ("); | |
399 | |
400 str->appendf("(%s, %s)", | |
401 gTileModeName[fTileModeX], | |
402 gTileModeName[fTileModeY]); | |
403 | |
404 str->append(" "); | |
405 fRawBitmap.toString(str); | |
406 | |
407 this->INHERITED::toString(str); | |
408 | |
409 str->append(")"); | |
410 } | |
411 #endif | |
412 | |
413 /////////////////////////////////////////////////////////////////////////////// | |
414 | |
415 #if SK_SUPPORT_GPU | |
416 | |
417 #include "GrTextureAccess.h" | |
418 #include "SkGr.h" | |
419 #include "effects/GrSimpleTextureEffect.h" | |
420 | |
421 sk_sp<GrFragmentProcessor> SkBitmapProcShader::asFragmentProcessor(const AsFPArg s& args) const { | |
422 SkMatrix matrix; | |
423 matrix.setIDiv(fRawBitmap.width(), fRawBitmap.height()); | |
424 | |
425 SkMatrix lmInverse; | |
426 if (!this->getLocalMatrix().invert(&lmInverse)) { | |
427 return nullptr; | |
428 } | |
429 if (args.fLocalMatrix) { | |
430 SkMatrix inv; | |
431 if (!args.fLocalMatrix->invert(&inv)) { | |
432 return nullptr; | |
433 } | |
434 lmInverse.postConcat(inv); | |
435 } | |
436 matrix.preConcat(lmInverse); | |
437 | |
438 SkShader::TileMode tm[] = { | |
439 (TileMode)fTileModeX, | |
440 (TileMode)fTileModeY, | |
441 }; | |
442 | |
443 // Must set wrap and filter on the sampler before requesting a texture. In t wo places below | |
444 // we check the matrix scale factors to determine how to interpret the filte r quality setting. | |
445 // This completely ignores the complexity of the drawVertices case where exp licit local coords | |
446 // are provided by the caller. | |
447 bool doBicubic; | |
448 GrTextureParams::FilterMode textureFilterMode = | |
449 GrSkFilterQualityToGrFilterMode(args.fFilterQuality, *args.fViewMatr ix, | |
450 this->getLocalMatrix(), &doBicubic); | |
451 GrTextureParams params(tm, textureFilterMode); | |
452 SkAutoTUnref<GrTexture> texture(GrRefCachedBitmapTexture(args.fContext, fRaw Bitmap, params, | |
453 args.fGammaTreatmen t)); | |
454 | |
455 if (!texture) { | |
456 SkErrorInternals::SetError( kInternalError_SkError, | |
457 "Couldn't convert bitmap to texture."); | |
458 return nullptr; | |
459 } | |
460 sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(fRawBitma p.colorSpace(), | |
461 args.fDst ColorSpace); | |
462 sk_sp<GrFragmentProcessor> inner; | |
463 if (doBicubic) { | |
464 inner = GrBicubicEffect::Make(texture, std::move(colorSpaceXform), matri x, tm); | |
465 } else { | |
466 inner = GrSimpleTextureEffect::Make(texture, std::move(colorSpaceXform), matrix, params); | |
467 } | |
468 | |
469 if (kAlpha_8_SkColorType == fRawBitmap.colorType()) { | |
470 return GrFragmentProcessor::MulOutputByInputUnpremulColor(std::move(inne r)); | |
471 } | |
472 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner)); | |
473 } | |
474 | |
475 #endif | |
OLD | NEW |