| Index: src/gpu/SkGr.cpp
|
| diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
|
| index 954bb808524243d181ed5066b6d84c5ef7b29449..5ceb473446fd4ada95db17b49a577d669959886f 100644
|
| --- a/src/gpu/SkGr.cpp
|
| +++ b/src/gpu/SkGr.cpp
|
| @@ -23,9 +23,12 @@
|
| #include "SkErrorInternals.h"
|
| #include "SkGrPixelRef.h"
|
| #include "SkMessageBus.h"
|
| +#include "SkMath.h"
|
| +#include "SkMipMapLevel.h"
|
| #include "SkPixelRef.h"
|
| #include "SkResourceCache.h"
|
| #include "SkTextureCompressor.h"
|
| +#include "SkTypes.h"
|
| #include "SkYUVPlanesCache.h"
|
| #include "effects/GrBicubicEffect.h"
|
| #include "effects/GrConstColorProcessor.h"
|
| @@ -285,6 +288,98 @@ void GrInstallBitmapUniqueKeyInvalidator(const GrUniqueKey& key, SkPixelRef* pix
|
| pixelRef->addGenIDChangeListener(new Invalidator(key));
|
| }
|
|
|
| +GrTexture* GrGenerateMipMapsAndUploadToTexture(GrContext* ctx, const SkBitmap& bitmap)
|
| +{
|
| + GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bitmap.info());
|
| + if (kIndex_8_SkColorType != bitmap.colorType() && !bitmap.readyToDraw()) {
|
| + GrTexture *texture = load_etc1_texture(ctx, bitmap, desc);
|
| + if (texture) {
|
| + return texture;
|
| + }
|
| + }
|
| +
|
| + GrTexture *texture = create_texture_from_yuv(ctx, bitmap, desc);
|
| + if (texture) {
|
| + return texture;
|
| + }
|
| +
|
| + SkASSERT(sizeof(int) <= sizeof(uint32_t));
|
| + if (bitmap.width() < 0 || bitmap.height() < 0) {
|
| + return nullptr;
|
| + }
|
| + const uint32_t baseWidth = static_cast<uint32_t>(bitmap.width());
|
| + const uint32_t baseHeight = static_cast<uint32_t>(bitmap.height());
|
| +
|
| + // OpenGL's spec requires that each mipmap level have height/width equal to
|
| + // max(1, floor(original_height / 2^i)
|
| + // (or original_width) where i is the mipmap level.
|
| + // Continue scaling down until both axes are size 1.
|
| +
|
| + const uint32_t largestAxis = SkTMax(baseWidth, baseHeight);
|
| + const int leadingZeros = SkCLZ(largestAxis);
|
| + // If the value 00011010 has 3 leading 0s then it has 5 significant bits
|
| + // (the bits which are not leading zeros)
|
| + const int significantBits = (sizeof(uint32_t) * 8) - leadingZeros;
|
| + // This is making the assumption that the size of a byte is 8 bits
|
| + // and that sizeof(uint32_t)'s implementation-defined behavior is 4.
|
| + if (significantBits < 0) {
|
| + return nullptr;
|
| + }
|
| + const uint32_t unsignedSignificantBits = static_cast<uint32_t>(significantBits);
|
| + const uint32_t mipLevelCount = unsignedSignificantBits;
|
| +
|
| + const bool isMipMapped = mipLevelCount > 1;
|
| + desc.fIsMipMapped = isMipMapped;
|
| +
|
| + SkTArray<SkBitmap> mipLevelBitmaps(mipLevelCount - 1);
|
| + mipLevelBitmaps.push_back_n(mipLevelCount - 1);
|
| +
|
| + SkTArray<SkMipMapLevel> texels(mipLevelCount);
|
| +
|
| + SkAutoLockPixels alp(bitmap);
|
| + if (!bitmap.readyToDraw()) {
|
| + return nullptr;
|
| + }
|
| +
|
| + SkMipMapLevel baseLevel(bitmap.getPixels(), bitmap.rowBytes(), baseWidth, baseHeight);
|
| + texels.push_back(baseLevel);
|
| +
|
| + SkPaint paint;
|
| + paint.setFilterQuality(kMedium_SkFilterQuality);
|
| +
|
| + for (uint32_t i = 1; i < mipLevelCount; i++) {
|
| + SkBitmap& currentMipBitmap = mipLevelBitmaps[i - 1];
|
| +
|
| + uint32_t twoToTheMipLevel = 1 << i;
|
| + uint32_t currentMipLevelWidth = SkTMax(1u, baseWidth / twoToTheMipLevel);
|
| + uint32_t currentMipLevelHeight = SkTMax(1u, baseHeight / twoToTheMipLevel);
|
| +
|
| + SkImageInfo info = SkImageInfo::Make(currentMipLevelWidth, currentMipLevelHeight,
|
| + bitmap.colorType(), bitmap.alphaType());
|
| + if (!currentMipBitmap.tryAllocPixels(info)) {
|
| + return nullptr;
|
| + }
|
| +
|
| + SkCanvas canvas(currentMipBitmap);
|
| + canvas.clear(SK_ColorTRANSPARENT);
|
| +
|
| + SkMatrix matrix;
|
| + matrix.setScale(static_cast<float>(currentMipLevelWidth) / baseWidth,
|
| + static_cast<float>(currentMipLevelHeight) / baseHeight);
|
| + canvas.save();
|
| + canvas.concat(matrix);
|
| + canvas.drawBitmap(bitmap, SkIntToScalar(0), SkIntToScalar(0), &paint);
|
| + canvas.restore();
|
| +
|
| + SkMipMapLevel currentMipLevel(currentMipBitmap.getPixels(),
|
| + currentMipBitmap.rowBytes(),
|
| + currentMipLevelWidth, currentMipLevelHeight);
|
| + texels.push_back(currentMipLevel);
|
| + }
|
| +
|
| + return ctx->textureProvider()->createTexture(desc, true, texels);
|
| +}
|
| +
|
| GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, const SkBitmap& bitmap,
|
| const GrTextureParams& params) {
|
| if (bitmap.getTexture()) {
|
|
|