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

Unified Diff: src/gpu/SkGr.cpp

Issue 1249543003: Creating functions for uploading a mipmapped texture. (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: Fixing bad rebase. Created 5 years, 2 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 side-by-side diff with in-line comments
Download patch
Index: src/gpu/SkGr.cpp
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 3c3f3e8fab99e9836564c571d912003901991c2e..c628067c39edbb4ab1b9304c86c719212cdd3a0d 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -22,9 +22,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"
@@ -48,7 +51,7 @@ GrSurfaceDesc GrImageInfoToSurfaceDesc(const SkImageInfo& info) {
return desc;
}
-void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& imageBounds) {
+void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& imageBounds, bool isMipMapped) {
SkASSERT(key);
SkASSERT(imageID);
SkASSERT(!imageBounds.isEmpty());
@@ -59,6 +62,12 @@ void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& ima
builder[2] = imageBounds.fTop;
builder[3] = imageBounds.fRight;
builder[4] = imageBounds.fBottom;
+ builder[5] = isMipMapped;
bsalomon 2015/10/28 16:40:45 This will cause us to potentially create two versi
+}
+
+void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& imageBounds) {
+ const bool isMipMapped = false;
+ GrMakeKeyFromImageID(key, imageID, imageBounds, isMipMapped);
}
GrPixelConfig GrIsCompressedTextureDataSupported(GrContext* ctx, SkData* data,
@@ -276,6 +285,77 @@ GrTexture* GrUploadBitmapToTexture(GrContext* ctx, const SkBitmap& bmp) {
////////////////////////////////////////////////////////////////////////////////
+static GrTexture* generate_mipmaps(GrContext* ctx,
+ const SkBitmap& bitmap) {
+ SkASSERT(sizeof(int) <= sizeof(uint32_t));
+ 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 has height/width equal to
+ // max(1, floor(original_height / 2^i)
+ // (or original_height) where i is the mipmap level.
+ // Keep 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, it has 5 significant bits
+ // (the bits which are not leading zeros)
+ const int significantBits = (sizeof(uint32_t) * 8) - leadingZeros;
+ if (significantBits < 0)
+ {
+ return nullptr;
+ }
+ const uint32_t unsignedSignificantBits = static_cast<uint32_t>(significantBits);
+ const uint32_t mipLevelCount = unsignedSignificantBits;
+
+ GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bitmap.info());
+ const bool isMipMapped = mipLevelCount > 1;
+ desc.fIsMipMapped = isMipMapped;
+
+ SkAutoPixmapUnlock srcUnlocker;
+ if (!bitmap.requestLock(&srcUnlocker)) {
+ return nullptr;
+ }
+ const SkPixmap& srcPixmap = srcUnlocker.pixmap();
+ if (nullptr == srcPixmap.addr()) {
+ return nullptr;
+ }
+
+ SkTArray<SkMipMapLevel> texels(mipLevelCount);
+ SkMipMapLevel baseLevel(srcPixmap.addr(), bitmap.rowBytes(), baseWidth, baseHeight);
+ texels.push_back(baseLevel);
+
+ SkTArray<SkBitmap> mipLevelBitmaps(mipLevelCount - 1);
+ mipLevelBitmaps.push_back_n(mipLevelCount - 1);
+
+ for (uint32_t i = 1; i < mipLevelCount; i++) {
+ SkBitmap& currentMipBitmap = mipLevelBitmaps[i - 1];
+
+ uint32_t twoToTheMipLevel = 1 << (i + 1);
+ uint32_t currentMipLevelWidth = SkTMax(1u, baseWidth / twoToTheMipLevel);
+ uint32_t currentMipLevelHeight = SkTMax(1u, baseHeight / twoToTheMipLevel);
+
+ SkImageInfo info = SkImageInfo::Make(currentMipLevelWidth, currentMipLevelHeight,
+ currentMipBitmap.colorType(),
+ bitmap.alphaType());
+ if (!currentMipBitmap.tryAllocPixels(info))
+ {
+ return nullptr;
+ }
+
+ SkCanvas canvas(currentMipBitmap);
+ canvas.clear(SK_ColorTRANSPARENT);
+ canvas.drawBitmap(bitmap, SkIntToScalar(0), SkIntToScalar(0));
+
+ SkMipMapLevel currentMipLevel(currentMipBitmap.getPixels(),
+ currentMipBitmap.rowBytes(),
+ currentMipLevelWidth, currentMipLevelHeight);
+ texels.push_back(currentMipLevel);
+ }
+
+ return ctx->textureProvider()->createTexture(desc, true, texels);
+}
+
class Bitmap_GrTextureParamsAdjuster : public GrTextureParamsAdjuster {
public:
Bitmap_GrTextureParamsAdjuster(const SkBitmap& bitmap)
@@ -293,7 +373,7 @@ public:
protected:
GrTexture* peekOriginalTexture() override { return fBitmap.getTexture(); }
- GrTexture* refOriginalTexture(GrContext* ctx) override {
+ GrTexture* refOriginalTexture(GrContext* ctx, const GrTextureParams& params) override {
GrTexture* tex = fBitmap.getTexture();
if (tex) {
return SkRef(tex);
@@ -306,7 +386,14 @@ protected:
}
}
- tex = GrUploadBitmapToTexture(ctx, fBitmap);
+ if (params.filterMode() == GrTextureParams::kMipMap_FilterMode) {
+ // If the SkBitmap is already backed by a texture, we do not want to read the contents
+ // back to the cpu and generate the mipmap only to send it back to the GPU.
+ SkASSERT(!tex);
+ tex = generate_mipmaps(ctx, fBitmap);
+ } else {
+ tex = GrUploadBitmapToTexture(ctx, fBitmap);
+ }
if (tex && fOriginalKey.isValid()) {
tex->resourcePriv().setUniqueKey(fOriginalKey);
InstallInvalidator(fOriginalKey, fBitmap.pixelRef());
« src/gpu/GrTexture.cpp ('K') | « src/gpu/SkGpuDevice.cpp ('k') | src/gpu/SkGrPixelRef.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698