Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(223)

Side by Side Diff: src/core/SkBitmapProcShader.cpp

Issue 2195893002: Always return ImageShader, even from SkShader::MakeBitmapShader (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: update serialize-8888 ignore list: skbug.com/5595 Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698