Index: src/image/SkImage_Gpu.cpp |
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp |
index fa911827489ad82a4482c9f50c94f9bc275f0ac2..0f4fff0a976e05c372be5a92e4a754ad179e9d78 100644 |
--- a/src/image/SkImage_Gpu.cpp |
+++ b/src/image/SkImage_Gpu.cpp |
@@ -16,6 +16,7 @@ |
#include "SkGrPixelRef.h" |
#include "SkGrPriv.h" |
#include "SkImage_Gpu.h" |
+#include "SkMipMap.h" |
#include "SkPixelRef.h" |
SkImage_Gpu::SkImage_Gpu(int w, int h, uint32_t uniqueID, SkAlphaType at, GrTexture* tex, |
@@ -362,7 +363,7 @@ private: |
}; |
size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& proxy, |
- const DeferredTextureImageUsageParams[], |
+ const DeferredTextureImageUsageParams params[], |
int paramCnt, void* buffer) const { |
const bool fillMode = SkToBool(buffer); |
if (fillMode && !SkIsAlign8(reinterpret_cast<intptr_t>(buffer))) { |
@@ -405,7 +406,27 @@ size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& prox |
SkASSERT(!pixmap.ctable()); |
} |
} |
+ bool shouldUseMipMaps = false; |
int mipMapLevelCount = 1; |
+ for (int currentParamIndex = paramCnt; currentParamIndex > 0; currentParamIndex--) { |
+ SkScalar minScaleFactor = params[currentParamIndex].fMatrix.getMinScale(); |
+ if ((params[currentParamIndex].fQuality == kMedium_SkFilterQuality || |
+ params[currentParamIndex].fQuality == kHigh_SkFilterQuality) && |
+ minScaleFactor != -1.f && minScaleFactor < 1.f) { |
bsalomon
2016/06/03 14:43:33
Do we not use mip maps when the matrix has perspec
cblume
2016/06/03 17:03:40
Hrmmm I think any time perspective is involved it
|
+ shouldUseMipMaps = true; |
+ mipMapLevelCount = SkMipMap::ComputeLevelCount(width(), height()); |
+ break; |
+ } |
+ } |
+ SkAlphaType at = this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType; |
+ if (shouldUseMipMaps) { |
+ for (int currentMipMapLevelIndex = mipMapLevelCount; currentMipMapLevelIndex > 0; |
+ currentMipMapLevelIndex--) { |
+ SkSize mipSize = SkMipMap::ComputeLevelSize(width(), height(), currentMipMapLevelIndex); |
+ SkImageInfo mipInfo = SkImageInfo::MakeN32(mipSize.fWidth, mipSize.fHeight, at); |
+ pixelSize += SkAlign8(SkAutoPixmapStorage::AllocSize(mipInfo, nullptr)); |
+ } |
+ } |
size_t size = 0; |
size_t dtiSize = SkAlign8(sizeof(DeferredTextureImage)); |
size += dtiSize; |
@@ -439,6 +460,27 @@ size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& prox |
dti->fData.fMipMapLevelCount = mipMapLevelCount; |
dti->fData.fMipMapLevelData[0].fPixelData = pixels; |
dti->fData.fMipMapLevelData[0].fRowBytes = rowBytes; |
+ |
+ // Fill in the mipmap levels if they exist |
+ intptr_t mipLevelPtr = bufferAsInt + pixelOffset; |
+ if (shouldUseMipMaps) { |
+ SkAutoTDelete<SkMipMap> mipmaps(SkMipMap::Build(pixmap, nullptr)); |
+ for (int currentMipMapLevelIndex = 1; currentMipMapLevelIndex < mipMapLevelCount; |
+ currentMipMapLevelIndex++) { |
+ SkSize prevMipSize = SkMipMap::ComputeLevelSize(width(), height(), currentMipMapLevelIndex); |
+ SkImageInfo prevMipInfo = SkImageInfo::MakeN32(prevMipSize.fWidth, prevMipSize.fHeight, at); |
+ mipLevelPtr += SkAlign8(SkAutoPixmapStorage::AllocSize(prevMipInfo, nullptr)); |
+ |
+ SkMipMap::Level currentMipMapLevel; |
+ mipmaps->getLevel(currentMipMapLevelIndex, ¤tMipMapLevel); |
+ memcpy(reinterpret_cast<void*>(mipLevelPtr), currentMipMapLevel.fPixmap.addr(), |
bsalomon
2016/06/03 14:43:33
It's too bad we have to memcpy here. Should we ext
cblume
2016/06/03 17:03:40
I agree @ memcpy. I would love to add a CL that mo
|
+ currentMipMapLevel.fPixmap.getSafeSize()); |
+ dti->fData.fMipMapLevelData[currentMipMapLevelIndex].fPixelData = |
+ reinterpret_cast<void*>(mipLevelPtr); |
+ dti->fData.fMipMapLevelData[currentMipMapLevelIndex].fRowBytes = |
+ currentMipMapLevel.fPixmap.rowBytes(); |
+ } |
+ } |
return size; |
} |
@@ -457,11 +499,23 @@ sk_sp<SkImage> SkImage::MakeFromDeferredTextureImageData(GrContext* context, con |
SkASSERT(dti->fData.fColorTableData); |
colorTable.reset(new SkColorTable(dti->fData.fColorTableData, dti->fData.fColorTableCnt)); |
} |
- SkASSERT(dti->fData.fMipMapLevelCount == 1); |
- SkPixmap pixmap; |
- pixmap.reset(dti->fData.fInfo, dti->fData.fMipMapLevelData[0].fPixelData, |
- dti->fData.fMipMapLevelData[0].fRowBytes, colorTable.get()); |
- return SkImage::MakeTextureFromPixmap(context, pixmap, budgeted); |
+ int mipLevelCount = dti->fData.fMipMapLevelCount; |
+ SkASSERT(mipLevelCount >= 1); |
+ if (mipLevelCount == 1) { |
+ SkPixmap pixmap; |
+ pixmap.reset(dti->fData.fInfo, dti->fData.fMipMapLevelData[0].fPixelData, |
+ dti->fData.fMipMapLevelData[0].fRowBytes, colorTable.get()); |
+ return SkImage::MakeTextureFromPixmap(context, pixmap, budgeted); |
+ } else { |
+ SkAutoTDeleteArray<GrMipLevel> texels(new GrMipLevel[mipLevelCount]); |
+ for (int i = 0; i < mipLevelCount; i++) { |
+ texels[i].fPixels = dti->fData.fMipMapLevelData[i].fPixelData; |
+ texels[i].fRowBytes = dti->fData.fMipMapLevelData[i].fRowBytes; |
+ } |
+ |
+ return SkImage::MakeTextureFromMipMap(context, dti->fData.fInfo, texels.get(), |
+ mipLevelCount, SkBudgeted::kYes); |
+ } |
} |
/////////////////////////////////////////////////////////////////////////////////////////////////// |