| 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 "GrTextureMaker.h" | 8 #include "GrTextureMaker.h" |
| 9 | 9 |
| 10 #include "SkGr.h" | 10 #include "SkGr.h" |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 #include "effects/GrDitherEffect.h" | 31 #include "effects/GrDitherEffect.h" |
| 32 #include "effects/GrPorterDuffXferProcessor.h" | 32 #include "effects/GrPorterDuffXferProcessor.h" |
| 33 #include "effects/GrXfermodeFragmentProcessor.h" | 33 #include "effects/GrXfermodeFragmentProcessor.h" |
| 34 #include "effects/GrYUVtoRGBEffect.h" | 34 #include "effects/GrYUVtoRGBEffect.h" |
| 35 | 35 |
| 36 #ifndef SK_IGNORE_ETC1_SUPPORT | 36 #ifndef SK_IGNORE_ETC1_SUPPORT |
| 37 # include "ktx.h" | 37 # include "ktx.h" |
| 38 # include "etc1.h" | 38 # include "etc1.h" |
| 39 #endif | 39 #endif |
| 40 | 40 |
| 41 bool GrTextureUsageSupported(const GrCaps& caps, int width, int height, SkImageU
sageType usage) { | |
| 42 if (caps.npotTextureTileSupport()) { | |
| 43 return true; | |
| 44 } | |
| 45 const bool is_pow2 = SkIsPow2(width) && SkIsPow2(height); | |
| 46 return is_pow2 || kUntiled_SkImageUsageType == usage; | |
| 47 } | |
| 48 | |
| 49 GrTextureParams GrImageUsageToTextureParams(SkImageUsageType usage) { | |
| 50 // Just need a params that will trigger the correct cache key / etc, since t
he usage doesn't | |
| 51 // tell us the specifics about filter level or specific tiling. | |
| 52 | |
| 53 const SkShader::TileMode tiles[] = { | |
| 54 SkShader::kClamp_TileMode, // kUntiled_SkImageUsageType | |
| 55 SkShader::kRepeat_TileMode, // kTiled_Unfiltered_SkImageUsageType | |
| 56 SkShader::kRepeat_TileMode, // kTiled_Filtered_SkImageUsageType | |
| 57 }; | |
| 58 | |
| 59 const GrTextureParams::FilterMode filters[] = { | |
| 60 GrTextureParams::kNone_FilterMode, // kUntiled_SkImageUsageType | |
| 61 GrTextureParams::kNone_FilterMode, // kTiled_Unfiltered_SkImageUsag
eType | |
| 62 GrTextureParams::kBilerp_FilterMode, // kTiled_Filtered_SkImageUsageT
ype | |
| 63 }; | |
| 64 | |
| 65 return GrTextureParams(tiles[usage], filters[usage]); | |
| 66 } | |
| 67 | |
| 68 /* Fill out buffer with the compressed format Ganesh expects from a colortable | 41 /* Fill out buffer with the compressed format Ganesh expects from a colortable |
| 69 based bitmap. [palette (colortable) + indices]. | 42 based bitmap. [palette (colortable) + indices]. |
| 70 | 43 |
| 71 At the moment Ganesh only supports 8bit version. If Ganesh allowed we others | 44 At the moment Ganesh only supports 8bit version. If Ganesh allowed we others |
| 72 we could detect that the colortable.count is <= 16, and then repack the | 45 we could detect that the colortable.count is <= 16, and then repack the |
| 73 indices as nibbles to save RAM, but it would take more time (i.e. a lot | 46 indices as nibbles to save RAM, but it would take more time (i.e. a lot |
| 74 slower than memcpy), so skipping that for now. | 47 slower than memcpy), so skipping that for now. |
| 75 | 48 |
| 76 Ganesh wants a full 256 palette entry, even though Skia's ctable is only as big | 49 Ganesh wants a full 256 palette entry, even though Skia's ctable is only as big |
| 77 as the colortable.count says it is. | 50 as the colortable.count says it is. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 for (int y = 0; y < bitmap.height(); y++) { | 90 for (int y = 0; y < bitmap.height(); y++) { |
| 118 memcpy(dst, src, width); | 91 memcpy(dst, src, width); |
| 119 src += rowBytes; | 92 src += rowBytes; |
| 120 dst += width; | 93 dst += width; |
| 121 } | 94 } |
| 122 } | 95 } |
| 123 } | 96 } |
| 124 | 97 |
| 125 //////////////////////////////////////////////////////////////////////////////// | 98 //////////////////////////////////////////////////////////////////////////////// |
| 126 | 99 |
| 127 static void get_stretch(const GrContext* ctx, int width, int height, | 100 static void get_stretch(const GrCaps& caps, int width, int height, |
| 128 const GrTextureParams* params, SkGrStretch* stretch) { | 101 const GrTextureParams& params, SkGrStretch* stretch) { |
| 129 stretch->fType = SkGrStretch::kNone_Type; | 102 stretch->fType = SkGrStretch::kNone_Type; |
| 130 bool doStretch = false; | 103 bool doStretch = false; |
| 131 if (params && params->isTiled() && !ctx->caps()->npotTextureTileSupport() && | 104 if (params.isTiled() && !caps.npotTextureTileSupport() && |
| 132 (!SkIsPow2(width) || !SkIsPow2(height))) { | 105 (!SkIsPow2(width) || !SkIsPow2(height))) { |
| 133 doStretch = true; | 106 doStretch = true; |
| 134 stretch->fWidth = GrNextPow2(SkTMax(width, ctx->caps()->minTextureSize(
))); | 107 stretch->fWidth = GrNextPow2(SkTMax(width, caps.minTextureSize())); |
| 135 stretch->fHeight = GrNextPow2(SkTMax(height, ctx->caps()->minTextureSize
())); | 108 stretch->fHeight = GrNextPow2(SkTMax(height, caps.minTextureSize())); |
| 136 } else if (width < ctx->caps()->minTextureSize() || height < ctx->caps()->mi
nTextureSize()) { | 109 } else if (width < caps.minTextureSize() || height < caps.minTextureSize())
{ |
| 137 // The small texture issues appear to be with tiling. Hence it seems ok
to scale them | 110 // The small texture issues appear to be with tiling. Hence it seems ok
to scale them |
| 138 // up using the GPU. If issues persist we may need to CPU-stretch. | 111 // up using the GPU. If issues persist we may need to CPU-stretch. |
| 139 doStretch = true; | 112 doStretch = true; |
| 140 stretch->fWidth = SkTMax(width, ctx->caps()->minTextureSize()); | 113 stretch->fWidth = SkTMax(width, caps.minTextureSize()); |
| 141 stretch->fHeight = SkTMax(height, ctx->caps()->minTextureSize()); | 114 stretch->fHeight = SkTMax(height, caps.minTextureSize()); |
| 142 } | 115 } |
| 143 if (doStretch) { | 116 if (doStretch) { |
| 144 if (params) { | 117 switch(params.filterMode()) { |
| 145 switch(params->filterMode()) { | 118 case GrTextureParams::kNone_FilterMode: |
| 146 case GrTextureParams::kNone_FilterMode: | 119 stretch->fType = SkGrStretch::kNearest_Type; |
| 147 stretch->fType = SkGrStretch::kNearest_Type; | 120 break; |
| 148 break; | 121 case GrTextureParams::kBilerp_FilterMode: |
| 149 case GrTextureParams::kBilerp_FilterMode: | 122 case GrTextureParams::kMipMap_FilterMode: |
| 150 case GrTextureParams::kMipMap_FilterMode: | 123 stretch->fType = SkGrStretch::kBilerp_Type; |
| 151 stretch->fType = SkGrStretch::kBilerp_Type; | 124 break; |
| 152 break; | |
| 153 } | |
| 154 } else { | |
| 155 stretch->fType = SkGrStretch::kBilerp_Type; | |
| 156 } | 125 } |
| 157 } else { | 126 } else { |
| 158 stretch->fWidth = -1; | 127 stretch->fWidth = -1; |
| 159 stretch->fHeight = -1; | 128 stretch->fHeight = -1; |
| 160 stretch->fType = SkGrStretch::kNone_Type; | 129 stretch->fType = SkGrStretch::kNone_Type; |
| 161 } | 130 } |
| 162 } | 131 } |
| 163 | 132 |
| 164 bool GrMakeStretchedKey(const GrUniqueKey& origKey, const SkGrStretch& stretch, | 133 bool GrMakeStretchedKey(const GrUniqueKey& origKey, const SkGrStretch& stretch, |
| 165 GrUniqueKey* stretchedKey) { | 134 GrUniqueKey* stretchedKey) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 183 | 152 |
| 184 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); | 153 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); |
| 185 GrUniqueKey::Builder builder(key, kDomain, 4); | 154 GrUniqueKey::Builder builder(key, kDomain, 4); |
| 186 builder[0] = imageID; | 155 builder[0] = imageID; |
| 187 builder[1] = subset.x(); | 156 builder[1] = subset.x(); |
| 188 builder[2] = subset.y(); | 157 builder[2] = subset.y(); |
| 189 builder[3] = subset.width() | (subset.height() << 16); | 158 builder[3] = subset.width() | (subset.height() << 16); |
| 190 } | 159 } |
| 191 | 160 |
| 192 void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& sub
set, | 161 void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& sub
set, |
| 193 const GrCaps& caps, SkImageUsageType usage) { | 162 const GrCaps& caps, const GrTextureParams& params) { |
| 194 const SkGrStretch::Type stretches[] = { | 163 SkGrStretch stretch; |
| 195 SkGrStretch::kNone_Type, // kUntiled_SkImageUsageType | 164 get_stretch(caps, subset.width(), subset.height(), params, &stretch); |
| 196 SkGrStretch::kNearest_Type, // kTiled_Unfiltered_SkImageUsageType | 165 if (SkGrStretch::kNone_Type != stretch.fType) { |
| 197 SkGrStretch::kBilerp_Type, // kTiled_Filtered_SkImageUsageType | |
| 198 }; | |
| 199 | |
| 200 if (!GrTextureUsageSupported(caps, subset.width(), subset.height(), usage))
{ | |
| 201 GrUniqueKey tmpKey; | 166 GrUniqueKey tmpKey; |
| 202 make_unstretched_key(&tmpKey, imageID, subset); | 167 make_unstretched_key(&tmpKey, imageID, subset); |
| 203 | |
| 204 SkGrStretch stretch; | |
| 205 stretch.fType = stretches[usage]; | |
| 206 stretch.fWidth = SkNextPow2(subset.width()); | |
| 207 stretch.fHeight = SkNextPow2(subset.height()); | |
| 208 if (!GrMakeStretchedKey(tmpKey, stretch, key)) { | 168 if (!GrMakeStretchedKey(tmpKey, stretch, key)) { |
| 209 goto UNSTRETCHED; | 169 *key = tmpKey; |
| 210 } | 170 } |
| 211 } else { | 171 } else { |
| 212 UNSTRETCHED: | |
| 213 make_unstretched_key(key, imageID, subset); | 172 make_unstretched_key(key, imageID, subset); |
| 214 } | 173 } |
| 215 } | 174 } |
| 216 | 175 |
| 217 static void make_image_keys(uint32_t imageID, const SkIRect& subset, const SkGrS
tretch& stretch, | 176 static void make_image_keys(uint32_t imageID, const SkIRect& subset, const SkGrS
tretch& stretch, |
| 218 GrUniqueKey* key, GrUniqueKey* stretchedKey) { | 177 GrUniqueKey* key, GrUniqueKey* stretchedKey) { |
| 219 make_unstretched_key(key, imageID, subset); | 178 make_unstretched_key(key, imageID, subset); |
| 220 if (SkGrStretch::kNone_Type != stretch.fType) { | 179 if (SkGrStretch::kNone_Type != stretch.fType) { |
| 221 GrMakeStretchedKey(*key, stretch, stretchedKey); | 180 GrMakeStretchedKey(*key, stretch, stretchedKey); |
| 222 } | 181 } |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 512 case SkGrStretch::kNone_Type: | 471 case SkGrStretch::kNone_Type: |
| 513 SkDEBUGFAIL("Shouldn't get here."); | 472 SkDEBUGFAIL("Shouldn't get here."); |
| 514 break; | 473 break; |
| 515 } | 474 } |
| 516 SkRect dstRect = SkRect::MakeWH(SkIntToScalar(stretch.fWidth), SkIntToScalar
(stretch.fHeight)); | 475 SkRect dstRect = SkRect::MakeWH(SkIntToScalar(stretch.fWidth), SkIntToScalar
(stretch.fHeight)); |
| 517 canvas.drawBitmapRect(bmp, dstRect, &paint); | 476 canvas.drawBitmapRect(bmp, dstRect, &paint); |
| 518 return stretched; | 477 return stretched; |
| 519 } | 478 } |
| 520 | 479 |
| 521 bool GrIsImageInCache(const GrContext* ctx, uint32_t imageID, const SkIRect& sub
set, | 480 bool GrIsImageInCache(const GrContext* ctx, uint32_t imageID, const SkIRect& sub
set, |
| 522 GrTexture* nativeTexture, const GrTextureParams* params) { | 481 GrTexture* nativeTexture, const GrTextureParams& params) { |
| 523 SkGrStretch stretch; | 482 SkGrStretch stretch; |
| 524 get_stretch(ctx, subset.width(), subset.height(), params, &stretch); | 483 get_stretch(*ctx->caps(), subset.width(), subset.height(), params, &stretch)
; |
| 525 | 484 |
| 526 // Handle the case where the bitmap/image is explicitly texture backed. | 485 // Handle the case where the bitmap/image is explicitly texture backed. |
| 527 if (nativeTexture) { | 486 if (nativeTexture) { |
| 528 if (SkGrStretch::kNone_Type == stretch.fType) { | 487 if (SkGrStretch::kNone_Type == stretch.fType) { |
| 529 return true; | 488 return true; |
| 530 } | 489 } |
| 531 const GrUniqueKey& key = nativeTexture->getUniqueKey(); | 490 const GrUniqueKey& key = nativeTexture->getUniqueKey(); |
| 532 if (!key.isValid()) { | 491 if (!key.isValid()) { |
| 533 return false; | 492 return false; |
| 534 } | 493 } |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 586 return true; | 545 return true; |
| 587 } | 546 } |
| 588 | 547 |
| 589 private: | 548 private: |
| 590 const SkBitmap fBitmap; | 549 const SkBitmap fBitmap; |
| 591 | 550 |
| 592 typedef GrTextureMaker INHERITED; | 551 typedef GrTextureMaker INHERITED; |
| 593 }; | 552 }; |
| 594 | 553 |
| 595 GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, const SkBitmap& bitmap, | 554 GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, const SkBitmap& bitmap, |
| 596 const GrTextureParams* params) { | 555 const GrTextureParams& params) { |
| 597 return Bitmap_GrTextureMaker(bitmap).refCachedTexture(ctx, params); | 556 return Bitmap_GrTextureMaker(bitmap).refCachedTexture(ctx, params); |
| 598 } | 557 } |
| 599 | 558 |
| 600 // TODO: make this be the canonical signature, and turn the version that takes G
rTextureParams* | |
| 601 // into a wrapper that contains the inverse of these tables. | |
| 602 GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, | |
| 603 const SkBitmap& bitmap, | |
| 604 SkImageUsageType usage) { | |
| 605 GrTextureParams params = GrImageUsageToTextureParams(usage); | |
| 606 return GrRefCachedBitmapTexture(ctx, bitmap, ¶ms); | |
| 607 } | |
| 608 | |
| 609 /////////////////////////////////////////////////////////////////////////////// | 559 /////////////////////////////////////////////////////////////////////////////// |
| 610 | 560 |
| 611 // alphatype is ignore for now, but if GrPixelConfig is expanded to encompass | 561 // alphatype is ignore for now, but if GrPixelConfig is expanded to encompass |
| 612 // alpha info, that will be considered. | 562 // alpha info, that will be considered. |
| 613 GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType, SkColorProf
ileType pt) { | 563 GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType, SkColorProf
ileType pt) { |
| 614 switch (ct) { | 564 switch (ct) { |
| 615 case kUnknown_SkColorType: | 565 case kUnknown_SkColorType: |
| 616 return kUnknown_GrPixelConfig; | 566 return kUnknown_GrPixelConfig; |
| 617 case kAlpha_8_SkColorType: | 567 case kAlpha_8_SkColorType: |
| 618 return kAlpha_8_GrPixelConfig; | 568 return kAlpha_8_GrPixelConfig; |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 921 "MIPMaps."); | 871 "MIPMaps."); |
| 922 textureFilterMode = GrTextureParams::kMipMap_FilterMode; | 872 textureFilterMode = GrTextureParams::kMipMap_FilterMode; |
| 923 break; | 873 break; |
| 924 | 874 |
| 925 } | 875 } |
| 926 return textureFilterMode; | 876 return textureFilterMode; |
| 927 } | 877 } |
| 928 | 878 |
| 929 ////////////////////////////////////////////////////////////////////////////////
//////////////// | 879 ////////////////////////////////////////////////////////////////////////////////
//////////////// |
| 930 | 880 |
| 931 GrTexture* GrTextureMaker::refCachedTexture(GrContext* ctx, SkImageUsageType usa
ge) { | 881 GrTexture* GrTextureMaker::refCachedTexture(GrContext* ctx, const GrTextureParam
s& params) { |
| 932 GrTextureParams params = GrImageUsageToTextureParams(usage); | |
| 933 return this->refCachedTexture(ctx, ¶ms); | |
| 934 } | |
| 935 | |
| 936 GrTexture* GrTextureMaker::refCachedTexture(GrContext* ctx, const GrTextureParam
s* params) { | |
| 937 SkGrStretch stretch; | 882 SkGrStretch stretch; |
| 938 get_stretch(ctx, this->width(), this->height(), params, &stretch); | 883 get_stretch(*ctx->caps(), this->width(), this->height(), params, &stretch); |
| 939 | 884 |
| 940 if (SkGrStretch::kNone_Type == stretch.fType) { | 885 if (SkGrStretch::kNone_Type == stretch.fType) { |
| 941 return this->onRefUnstretchedTexture(ctx); | 886 return this->onRefUnstretchedTexture(ctx); |
| 942 } | 887 } |
| 943 | 888 |
| 944 GrUniqueKey stretchedKey; | 889 GrUniqueKey stretchedKey; |
| 945 if (this->onMakeStretchedKey(stretch, &stretchedKey)) { | 890 if (this->onMakeStretchedKey(stretch, &stretchedKey)) { |
| 946 GrTexture* result = ctx->textureProvider()->findAndRefTextureByUniqueKey
(stretchedKey); | 891 GrTexture* result = ctx->textureProvider()->findAndRefTextureByUniqueKey
(stretchedKey); |
| 947 if (result) { | 892 if (result) { |
| 948 return result; | 893 return result; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 974 SkBitmap stretchedBmp = stretch_on_cpu(bitmap, stretch); | 919 SkBitmap stretchedBmp = stretch_on_cpu(bitmap, stretch); |
| 975 return create_unstretched_bitmap_texture(ctx, stretchedBmp, GrUniqueKey(
)); | 920 return create_unstretched_bitmap_texture(ctx, stretchedBmp, GrUniqueKey(
)); |
| 976 } else { | 921 } else { |
| 977 SkAutoTUnref<GrTexture> unstretched(this->onRefUnstretchedTexture(ctx)); | 922 SkAutoTUnref<GrTexture> unstretched(this->onRefUnstretchedTexture(ctx)); |
| 978 if (!unstretched) { | 923 if (!unstretched) { |
| 979 return nullptr; | 924 return nullptr; |
| 980 } | 925 } |
| 981 return stretch_texture(unstretched, stretch, nullptr, GrUniqueKey()); | 926 return stretch_texture(unstretched, stretch, nullptr, GrUniqueKey()); |
| 982 } | 927 } |
| 983 } | 928 } |
| OLD | NEW |