Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2010 Google Inc. | 2 * Copyright 2010 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 "SkGr.h" | 8 #include "SkGr.h" |
| 9 | 9 |
| 10 #include "GrCaps.h" | 10 #include "GrCaps.h" |
| (...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 496 break; | 496 break; |
| 497 case Stretch::kNone_Type: | 497 case Stretch::kNone_Type: |
| 498 SkDEBUGFAIL("Shouldn't get here."); | 498 SkDEBUGFAIL("Shouldn't get here."); |
| 499 break; | 499 break; |
| 500 } | 500 } |
| 501 SkRect dstRect = SkRect::MakeWH(SkIntToScalar(stretch.fWidth), SkIntToScalar (stretch.fHeight)); | 501 SkRect dstRect = SkRect::MakeWH(SkIntToScalar(stretch.fWidth), SkIntToScalar (stretch.fHeight)); |
| 502 canvas.drawBitmapRect(bmp, dstRect, &paint); | 502 canvas.drawBitmapRect(bmp, dstRect, &paint); |
| 503 return stretched; | 503 return stretched; |
| 504 } | 504 } |
| 505 | 505 |
| 506 static GrTexture* create_bitmap_texture(GrContext* ctx, | |
| 507 const SkBitmap& bmp, | |
| 508 const Stretch& stretch, | |
| 509 const GrUniqueKey& unstretchedKey, | |
| 510 const GrUniqueKey& stretchedKey) { | |
| 511 if (Stretch::kNone_Type != stretch.fType) { | |
| 512 SkAutoTUnref<GrTexture> unstretched; | |
| 513 // Check if we have the unstretched version in the cache, if not create it. | |
| 514 if (unstretchedKey.isValid()) { | |
| 515 unstretched.reset(ctx->textureProvider()->findAndRefTextureByUniqueK ey(unstretchedKey)); | |
| 516 } | |
| 517 if (!unstretched) { | |
| 518 unstretched.reset(create_unstretched_bitmap_texture(ctx, bmp, unstre tchedKey)); | |
| 519 if (!unstretched) { | |
| 520 // We might not have been able to create a unstrecthed texture b ecause it is smaller | |
| 521 // than the min texture size. In that case do cpu stretching. | |
| 522 SkBitmap stretchedBmp = stretch_on_cpu(bmp, stretch); | |
| 523 return create_unstretched_bitmap_texture(ctx, stretchedBmp, stre tchedKey); | |
| 524 } | |
| 525 } | |
| 526 return stretch_texture(unstretched, stretch, bmp.pixelRef(), stretchedKe y); | |
| 527 } | |
| 528 return create_unstretched_bitmap_texture(ctx, bmp, unstretchedKey); | |
| 529 } | |
| 530 | |
| 531 bool GrIsImageInCache(const GrContext* ctx, uint32_t imageID, const SkIRect& sub set, | 506 bool GrIsImageInCache(const GrContext* ctx, uint32_t imageID, const SkIRect& sub set, |
| 532 GrTexture* nativeTexture, const GrTextureParams* params) { | 507 GrTexture* nativeTexture, const GrTextureParams* params) { |
| 533 Stretch stretch; | 508 Stretch stretch; |
| 534 get_stretch(ctx, subset.width(), subset.height(), params, &stretch); | 509 get_stretch(ctx, subset.width(), subset.height(), params, &stretch); |
| 535 | 510 |
| 536 // Handle the case where the bitmap/image is explicitly texture backed. | 511 // Handle the case where the bitmap/image is explicitly texture backed. |
| 537 if (nativeTexture) { | 512 if (nativeTexture) { |
| 538 if (Stretch::kNone_Type == stretch.fType) { | 513 if (Stretch::kNone_Type == stretch.fType) { |
| 539 return true; | 514 return true; |
| 540 } | 515 } |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 555 | 530 |
| 556 bool GrIsBitmapInCache(const GrContext* ctx, const SkBitmap& bitmap, | 531 bool GrIsBitmapInCache(const GrContext* ctx, const SkBitmap& bitmap, |
| 557 const GrTextureParams* params) { | 532 const GrTextureParams* params) { |
| 558 if (bitmap.isVolatile()) { | 533 if (bitmap.isVolatile()) { |
| 559 return false; // we don't cache volatile bitmaps. | 534 return false; // we don't cache volatile bitmaps. |
| 560 } | 535 } |
| 561 return GrIsImageInCache(ctx, bitmap.getGenerationID(), bitmap.getSubset(), b itmap.getTexture(), | 536 return GrIsImageInCache(ctx, bitmap.getGenerationID(), bitmap.getSubset(), b itmap.getTexture(), |
| 562 params); | 537 params); |
| 563 } | 538 } |
| 564 | 539 |
| 565 GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, | 540 class GrTextureMaker { |
| 566 const SkBitmap& bitmap, | 541 public: |
| 567 const GrTextureParams* params) { | 542 GrTextureMaker(int width, int height) : fWidth(width), fHeight(height) {} |
| 568 | 543 |
| 544 int width() const { return fWidth; } | |
| 545 int height() const { return fHeight; } | |
| 546 | |
| 547 GrTexture* refCachedTexture(GrContext*, const GrTextureParams*); | |
| 548 | |
| 549 protected: | |
| 550 /** | |
| 551 * Return the maker's "original" unstretched texture. It is the responsibil ity of the maker | |
| 552 * to make this efficient ... if the texture is being generated, the maker must handle | |
| 553 * caching it. | |
| 554 */ | |
| 555 virtual GrTexture* onRefUnstretchedTexture(GrContext*) = 0; | |
| 556 | |
| 557 /** | |
| 558 * If we need to stretch the maker's original texture, the maker is asked t o return a key | |
| 559 * that identifies its origianl + the stretch parameter. If the maker does not want to cache | |
| 560 * the stretched version (e.g. the maker is volatile), this should ignore t he key parameter | |
| 561 * and return false. | |
| 562 */ | |
| 563 virtual bool onMakeStretchedKey(const Stretch&, GrUniqueKey* stretchedKey) = 0; | |
| 564 | |
| 565 /** | |
| 566 * Return a new (uncached) texture that is the stretch of the maker's origi nal. | |
| 567 * | |
| 568 * The base-class handles general logic for this, and only needs access to the following | |
| 569 * methods: | |
| 570 * - onRefUnstretchedTexture() | |
| 571 * - onGetROBitmkap() | |
|
bsalomon
2015/09/29 19:23:29
ROBitmap
reed1
2015/09/29 19:38:13
Done.
| |
| 572 * | |
| 573 * Subclass may override this if they can handle stretching more efficientl y. | |
| 574 */ | |
| 575 virtual GrTexture* onGenerateStretchedTexture(GrContext*, const Stretch&); | |
| 576 | |
| 577 /** | |
| 578 * If a stretched version of the texture is generated, it may be cached (as suming that | |
| 579 * onMakeStretchedKey() returns true). In that case, the maker is notified in case it | |
| 580 * wants to note that for when the maker is destroyed. | |
| 581 */ | |
| 582 virtual void onNotifyStretchCached(const GrUniqueKey& stretchedKey) = 0; | |
| 583 | |
| 584 /** | |
| 585 * Some GPUs are unreliable w/ very small texture sizes. If we run into tha t case, this | |
| 586 * method will be called (in service of onGenerateStretchedTexture) to retu rn a raster version | |
| 587 * of the original texture. | |
| 588 */ | |
| 589 virtual bool onGetROBitmap(SkBitmap*) = 0; | |
| 590 | |
| 591 private: | |
| 592 const int fWidth; | |
| 593 const int fHeight; | |
| 594 }; | |
| 595 | |
| 596 GrTexture* GrTextureMaker::onGenerateStretchedTexture(GrContext* ctx, const Stre tch& stretch) { | |
| 597 if (this->width() < ctx->caps()->minTextureSize() || | |
| 598 this->height() < ctx->caps()->minTextureSize()) | |
| 599 { | |
| 600 // we can't trust our ability to use HW to perform the stretch, so we re quest | |
| 601 // a raster instead, and perform the stretch on the CPU. | |
| 602 SkBitmap bitmap; | |
| 603 if (!this->onGetROBitmap(&bitmap)) { | |
| 604 return nullptr; | |
| 605 } | |
| 606 SkBitmap stretchedBmp = stretch_on_cpu(bitmap, stretch); | |
| 607 return create_unstretched_bitmap_texture(ctx, stretchedBmp, GrUniqueKey( )); | |
| 608 } else { | |
| 609 SkAutoTUnref<GrTexture> unstretched(this->onRefUnstretchedTexture(ctx)); | |
| 610 if (!unstretched) { | |
| 611 return nullptr; | |
| 612 } | |
| 613 return stretch_texture(unstretched, stretch, nullptr, GrUniqueKey()); | |
| 614 } | |
| 615 } | |
| 616 | |
|
bsalomon
2015/09/29 19:23:29
extra \n
reed1
2015/09/29 19:38:13
Done.
| |
| 617 | |
| 618 GrTexture* GrTextureMaker::refCachedTexture(GrContext* ctx, const GrTextureParam s* params) { | |
| 569 Stretch stretch; | 619 Stretch stretch; |
| 570 get_stretch(ctx, bitmap.width(), bitmap.height(), params, &stretch); | 620 get_stretch(ctx, this->width(), this->height(), params, &stretch); |
| 571 | 621 |
| 572 GrTexture* result = bitmap.getTexture(); | 622 if (Stretch::kNone_Type == stretch.fType) { |
| 573 if (result) { | 623 return this->onRefUnstretchedTexture(ctx); |
| 574 if (Stretch::kNone_Type == stretch.fType) { | |
| 575 return SkRef(result); | |
| 576 } | |
| 577 GrUniqueKey stretchedKey; | |
| 578 // Don't create a key for the resized version if the bmp is volatile. | |
| 579 if (!bitmap.isVolatile()) { | |
| 580 const GrUniqueKey& key = result->getUniqueKey(); | |
| 581 if (key.isValid()) { | |
| 582 make_stretched_key(key, stretch, &stretchedKey); | |
| 583 GrTexture* stretched = | |
| 584 ctx->textureProvider()->findAndRefTextureByUniqueKey(stretch edKey); | |
| 585 if (stretched) { | |
| 586 return stretched; | |
| 587 } | |
| 588 } | |
| 589 } | |
| 590 return stretch_texture(result, stretch, bitmap.pixelRef(), stretchedKey) ; | |
| 591 } | 624 } |
| 592 | 625 |
| 593 GrUniqueKey key, resizedKey; | 626 GrUniqueKey stretchedKey; |
| 594 | 627 if (this->onMakeStretchedKey(stretch, &stretchedKey)) { |
| 595 if (!bitmap.isVolatile()) { | 628 GrTexture* result = ctx->textureProvider()->findAndRefTextureByUniqueKey (stretchedKey); |
| 596 // If the bitmap isn't changing try to find a cached copy first. | |
| 597 make_image_keys(bitmap.getGenerationID(), bitmap.getSubset(), stretch, & key, &resizedKey); | |
| 598 | |
| 599 result = ctx->textureProvider()->findAndRefTextureByUniqueKey( | |
| 600 resizedKey.isValid() ? resizedKey : key); | |
| 601 if (result) { | 629 if (result) { |
| 602 return result; | 630 return result; |
| 603 } | 631 } |
| 604 } | 632 } |
| 605 | 633 |
| 606 result = create_bitmap_texture(ctx, bitmap, stretch, key, resizedKey); | 634 GrTexture* result = this->onGenerateStretchedTexture(ctx, stretch); |
| 607 if (result) { | 635 if (!result) { |
| 608 return result; | 636 return nullptr; |
| 609 } | 637 } |
| 610 | 638 |
| 611 SkErrorInternals::SetError( kInternalError_SkError, | 639 if (stretchedKey.isValid()) { |
| 612 "---- failed to create texture for cache [%d %d] \n", | 640 ctx->textureProvider()->assignUniqueKeyToTexture(stretchedKey, result); |
| 613 bitmap.width(), bitmap.height()); | 641 this->onNotifyStretchCached(stretchedKey); |
| 642 } | |
| 643 return result; | |
| 644 } | |
| 614 | 645 |
| 615 return nullptr; | 646 class Bitmap_GrTextureMaker : public GrTextureMaker { |
| 647 public: | |
| 648 Bitmap_GrTextureMaker(const SkBitmap& bitmap) | |
| 649 : INHERITED(bitmap.width(), bitmap.height()) | |
| 650 , fBitmap(bitmap) | |
| 651 {} | |
| 652 | |
| 653 protected: | |
| 654 GrTexture* onRefUnstretchedTexture(GrContext* ctx) override { | |
| 655 GrTexture* tex = fBitmap.getTexture(); | |
| 656 if (tex) { | |
| 657 return SkRef(tex); | |
| 658 } | |
| 659 | |
| 660 GrUniqueKey unstretchedKey; | |
| 661 make_unstretched_key(&unstretchedKey, fBitmap.getGenerationID(), fBitmap .getSubset()); | |
| 662 return create_unstretched_bitmap_texture(ctx, fBitmap, unstretchedKey); | |
| 663 } | |
| 664 | |
| 665 bool onMakeStretchedKey(const Stretch& stretch, GrUniqueKey* stretchedKey) o verride { | |
| 666 if (fBitmap.isVolatile()) { | |
| 667 return false; | |
| 668 } | |
| 669 | |
| 670 GrUniqueKey unstretchedKey; | |
| 671 make_unstretched_key(&unstretchedKey, fBitmap.getGenerationID(), fBitmap .getSubset()); | |
| 672 return make_stretched_key(unstretchedKey, stretch, stretchedKey); | |
| 673 } | |
| 674 | |
| 675 void onNotifyStretchCached(const GrUniqueKey& stretchedKey) override { | |
| 676 fBitmap.pixelRef()->addGenIDChangeListener(new BitmapInvalidator(stretch edKey)); | |
| 677 } | |
| 678 | |
| 679 bool onGetROBitmap(SkBitmap* bitmap) override { | |
| 680 *bitmap = fBitmap; | |
| 681 return true; | |
| 682 } | |
| 683 | |
| 684 private: | |
| 685 const SkBitmap fBitmap; | |
| 686 | |
| 687 typedef GrTextureMaker INHERITED; | |
| 688 }; | |
| 689 | |
| 690 GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, const SkBitmap& bitmap, | |
| 691 const GrTextureParams* params) { | |
| 692 return Bitmap_GrTextureMaker(bitmap).refCachedTexture(ctx, params); | |
| 616 } | 693 } |
| 617 | 694 |
| 618 // TODO: make this be the canonical signature, and turn the version that takes G rTextureParams* | 695 // TODO: make this be the canonical signature, and turn the version that takes G rTextureParams* |
| 619 // into a wrapper that contains the inverse of these tables. | 696 // into a wrapper that contains the inverse of these tables. |
| 620 GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, | 697 GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, |
| 621 const SkBitmap& bitmap, | 698 const SkBitmap& bitmap, |
| 622 SkImageUsageType usage) { | 699 SkImageUsageType usage) { |
| 623 // Just need a params that will trigger the correct cache key / etc, since t he usage doesn't | 700 // Just need a params that will trigger the correct cache key / etc, since t he usage doesn't |
| 624 // tell us the specifics about filter level or specific tiling. | 701 // tell us the specifics about filter level or specific tiling. |
| 625 | 702 |
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 941 SkErrorInternals::SetError( kInvalidPaint_SkError, | 1018 SkErrorInternals::SetError( kInvalidPaint_SkError, |
| 942 "Sorry, I don't understand the filtering " | 1019 "Sorry, I don't understand the filtering " |
| 943 "mode you asked for. Falling back to " | 1020 "mode you asked for. Falling back to " |
| 944 "MIPMaps."); | 1021 "MIPMaps."); |
| 945 textureFilterMode = GrTextureParams::kMipMap_FilterMode; | 1022 textureFilterMode = GrTextureParams::kMipMap_FilterMode; |
| 946 break; | 1023 break; |
| 947 | 1024 |
| 948 } | 1025 } |
| 949 return textureFilterMode; | 1026 return textureFilterMode; |
| 950 } | 1027 } |
| OLD | NEW |