aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar cblume <cblume@chromium.org>2016-08-09 13:45:56 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-08-09 13:45:56 -0700
commitd6113140f7ae8996f679ac6698a60fb8c1386da3 (patch)
treef641a12df7ca225733bd164297485f189f254db9
parent8eccc308c8adcdf26ffc7c4dd538b71f33c6f22b (diff)
Store mipmap levels in deferred texture image
This is a follow-up to https://codereview.chromium.org/2034933003/ which was reverted due to a memory leak. When creating the deferred texture image, detect if using medium / high quality. If so, generate and store mipmaps in the deferred texture image. When creating a texture from that be sure to read it back out. BUG=578304 GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2115023002 Review-Url: https://codereview.chromium.org/2115023002
-rw-r--r--gm/deferredtextureimage.cpp195
-rw-r--r--gm/deferredtextureimagedata.cpp81
-rw-r--r--include/core/SkImage.h6
-rw-r--r--src/image/SkImage.cpp8
-rw-r--r--src/image/SkImage_Gpu.cpp126
-rw-r--r--tests/ImageTest.cpp7
6 files changed, 317 insertions, 106 deletions
diff --git a/gm/deferredtextureimage.cpp b/gm/deferredtextureimage.cpp
new file mode 100644
index 0000000000..6c7dd447cc
--- /dev/null
+++ b/gm/deferredtextureimage.cpp
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include <vector>
+
+#include "gm.h"
+#include "GrContext.h"
+#include "SkMipMap.h"
+#include "Resources.h"
+
+#if SK_SUPPORT_GPU
+
+// Helper function that uploads the given SkImage using MakdeFromDeferredTextureImageData and then
+// draws the uploaded version at the specified coordinates.
+static void DrawDeferredTextureImageData(SkCanvas* canvas,
+ SkImage::DeferredTextureImageUsageParams* params) {
+ GrContext* context = canvas->getGrContext();
+ if (!context) {
+ skiagm::GM::DrawGpuOnlyMessage(canvas);
+ return;
+ }
+ SkAutoTUnref<GrContextThreadSafeProxy> proxy(context->threadSafeProxy());
+
+
+
+ sk_sp<SkImage> encodedImage = GetResourceAsImage("mandrill_512.png");
+ if (!encodedImage) {
+ SkDebugf("\nCould not load resource.\n");
+ return;
+ }
+
+ size_t requiredMemoryInBytes = encodedImage->getDeferredTextureImageData(
+ *proxy, params, 1, nullptr, SkSourceGammaTreatment::kRespect);
+ if (requiredMemoryInBytes == 0) {
+ SkDebugf("\nCould not create DeferredTextureImageData.\n");
+ return;
+ }
+
+ std::vector<uint8_t> memory;
+ memory.resize(requiredMemoryInBytes);
+ encodedImage->getDeferredTextureImageData(
+ *proxy, params, 1, memory.data(), SkSourceGammaTreatment::kRespect);
+ sk_sp<SkImage> uploadedEncodedImage = SkImage::MakeFromDeferredTextureImageData(
+ context, memory.data(), SkBudgeted::kNo);
+
+ canvas->drawImage(uploadedEncodedImage, 10, 10);
+
+
+
+ SkBitmap bitmap;
+ if (!GetResourceAsBitmap("mandrill_512.png", &bitmap)) {
+ SkDebugf("\nCould not decode resource.\n");
+ return;
+ }
+ sk_sp<SkImage> decodedImage = SkImage::MakeFromBitmap(bitmap);
+
+ requiredMemoryInBytes = decodedImage->getDeferredTextureImageData(
+ *proxy, params, 1, nullptr, SkSourceGammaTreatment::kRespect);
+ if (requiredMemoryInBytes == 0) {
+ SkDebugf("\nCould not create DeferredTextureImageData.\n");
+ return;
+ }
+
+ memory.resize(requiredMemoryInBytes);
+ decodedImage->getDeferredTextureImageData(
+ *proxy, params, 1, memory.data(), SkSourceGammaTreatment::kRespect);
+ sk_sp<SkImage> uploadedDecodedImage = SkImage::MakeFromDeferredTextureImageData(
+ context, memory.data(), SkBudgeted::kNo);
+
+ canvas->drawImage(uploadedDecodedImage, 512 + 20, 10);
+}
+
+static void DrawDeferredTextureImageMipMapTree(SkCanvas* canvas, SkImage* image,
+ SkImage::DeferredTextureImageUsageParams* params) {
+ GrContext* context = canvas->getGrContext();
+ if (!context) {
+ skiagm::GM::DrawGpuOnlyMessage(canvas);
+ return;
+ }
+ SkAutoTUnref<GrContextThreadSafeProxy> proxy(context->threadSafeProxy());
+
+ SkPaint paint;
+ paint.setFilterQuality(params->fQuality);
+
+ int mipLevelCount = SkMipMap::ComputeLevelCount(512, 512);
+ size_t requiredMemoryInBytes = image->getDeferredTextureImageData(
+ *proxy, params, 1, nullptr, SkSourceGammaTreatment::kRespect);
+ if (requiredMemoryInBytes == 0) {
+ SkDebugf("\nCould not create DeferredTextureImageData.\n");
+ return;
+ }
+
+ std::vector<uint8_t> memory;
+ memory.resize(requiredMemoryInBytes);
+ image->getDeferredTextureImageData(
+ *proxy, params, 1, memory.data(), SkSourceGammaTreatment::kRespect);
+ sk_sp<SkImage> uploadedImage = SkImage::MakeFromDeferredTextureImageData(
+ context, memory.data(), SkBudgeted::kNo);
+
+ // draw a column using deferred texture images
+ SkScalar offsetHeight = 10.f;
+ // handle base mipmap level
+ canvas->save();
+ canvas->translate(10.f, offsetHeight);
+ canvas->drawImage(uploadedImage, 0, 0, &paint);
+ canvas->restore();
+ offsetHeight += 512 + 10;
+ // handle generated mipmap levels
+ for (int i = 0; i < mipLevelCount; i++) {
+ SkISize mipSize = SkMipMap::ComputeLevelSize(512, 512, i);
+ canvas->save();
+ canvas->translate(10.f, offsetHeight);
+ canvas->scale(mipSize.width() / 512.f, mipSize.height() / 512.f);
+ canvas->drawImage(uploadedImage, 0, 0, &paint);
+ canvas->restore();
+ offsetHeight += mipSize.height() + 10;
+ }
+
+ // draw a column using SkImage
+ offsetHeight = 10;
+ // handle base mipmap level
+ canvas->save();
+ canvas->translate(512.f + 20.f, offsetHeight);
+ canvas->drawImage(image, 0, 0, &paint);
+ canvas->restore();
+ offsetHeight += 512 + 10;
+ // handle generated mipmap levels
+ for (int i = 0; i < mipLevelCount; i++) {
+ SkISize mipSize = SkMipMap::ComputeLevelSize(512, 512, i);
+ canvas->save();
+ canvas->translate(512.f + 20.f, offsetHeight);
+ canvas->scale(mipSize.width() / 512.f, mipSize.height() / 512.f);
+ canvas->drawImage(image, 0, 0, &paint);
+ canvas->restore();
+ offsetHeight += mipSize.height() + 10;
+ }
+}
+
+DEF_SIMPLE_GM(deferred_texture_image_default, canvas, 512 + 512 + 30, 512 + 20) {
+ SkImage::DeferredTextureImageUsageParams params;
+ DrawDeferredTextureImageData(canvas, &params);
+}
+
+DEF_SIMPLE_GM(deferred_texture_image_none, canvas, 512 + 512 + 30, 512 + 20) {
+ SkImage::DeferredTextureImageUsageParams params;
+ params.fPreScaleMipLevel = 0;
+ params.fQuality = kNone_SkFilterQuality;
+ DrawDeferredTextureImageData(canvas, &params);
+}
+
+DEF_SIMPLE_GM(deferred_texture_image_low, canvas, 512 + 512 + 30, 512 + 20) {
+ SkImage::DeferredTextureImageUsageParams params;
+ params.fPreScaleMipLevel = 0;
+ params.fQuality = kLow_SkFilterQuality;
+ DrawDeferredTextureImageData(canvas, &params);
+}
+
+DEF_SIMPLE_GM(deferred_texture_image_medium_encoded, canvas, 512 + 512 + 30, 1110) {
+ sk_sp<SkImage> encodedImage = GetResourceAsImage("mandrill_512.png");
+ if (!encodedImage) {
+ SkDebugf("\nCould not load resource.\n");
+ return;
+ }
+
+ SkImage::DeferredTextureImageUsageParams params;
+ params.fMatrix = SkMatrix::MakeScale(0.25f, 0.25f);
+ params.fQuality = kMedium_SkFilterQuality;
+ DrawDeferredTextureImageMipMapTree(canvas, encodedImage.get(), &params);
+}
+
+DEF_SIMPLE_GM(deferred_texture_image_medium_decoded, canvas, 512 + 512 + 30, 1110) {
+ SkBitmap bitmap;
+ if (!GetResourceAsBitmap("mandrill_512.png", &bitmap)) {
+ SkDebugf("\nCould not decode resource.\n");
+ return;
+ }
+ sk_sp<SkImage> decodedImage = SkImage::MakeFromBitmap(bitmap);
+
+ SkImage::DeferredTextureImageUsageParams params;
+ params.fMatrix = SkMatrix::MakeScale(0.25f, 0.25f);
+ params.fQuality = kMedium_SkFilterQuality;
+ DrawDeferredTextureImageMipMapTree(canvas, decodedImage.get(), &params);
+}
+
+DEF_SIMPLE_GM(deferred_texture_image_high, canvas, 512 + 512 + 30, 512 + 20) {
+ SkImage::DeferredTextureImageUsageParams params;
+ params.fPreScaleMipLevel = 0;
+ params.fQuality = kHigh_SkFilterQuality;
+ DrawDeferredTextureImageData(canvas, &params);
+}
+
+#endif
diff --git a/gm/deferredtextureimagedata.cpp b/gm/deferredtextureimagedata.cpp
deleted file mode 100644
index 0a3b40213a..0000000000
--- a/gm/deferredtextureimagedata.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include <vector>
-
-#include "gm.h"
-#include "GrContext.h"
-#include "Resources.h"
-#include "SkImage.h"
-
-#if SK_SUPPORT_GPU
-
-// Helper function that uploads the given SkImage using MakdeFromDeferredTextureImageData and then
-// draws the uploaded version at the specified coordinates.
-static bool DrawDeferredTextureImageData(GrContext* context, SkCanvas* canvas, SkImage* image,
- SkImage::DeferredTextureImageUsageParams* params,
- SkScalar x, SkScalar y) {
- SkAutoTUnref<GrContextThreadSafeProxy> proxy(context->threadSafeProxy());
- size_t deferredSize = image->getDeferredTextureImageData(*proxy, params, 1, nullptr);
- if (deferredSize == 0) {
- SkDebugf("\nCould not create DeferredTextureImageData.\n");
- return false;
- }
-
- std::vector<uint8_t> memory;
- memory.resize(deferredSize);
- image->getDeferredTextureImageData(*proxy, params, 1, memory.data());
- sk_sp<SkImage> uploadedImage =
- SkImage::MakeFromDeferredTextureImageData(context, memory.data(), SkBudgeted::kNo);
- canvas->drawImage(uploadedImage, x, y);
-
- return true;
-}
-
-DEF_SIMPLE_GM(deferred_texture_image_data, canvas, 60, 10) {
- GrContext* context = canvas->getGrContext();
- if (!context) {
- skiagm::GM::DrawGpuOnlyMessage(canvas);
- return;
- }
-
- sk_sp<SkImage> encodedImage = GetResourceAsImage("randPixels.png");
- if (!encodedImage) {
- SkDebugf("\nCould not load resource.\n");
- return;
- }
-
- SkBitmap bitmap;
- if (!GetResourceAsBitmap("randPixels.png", &bitmap)) {
- SkDebugf("\nCould not decode resource.\n");
- return;
- }
-
- sk_sp<SkImage> decodedImage = SkImage::MakeFromBitmap(bitmap);
-
- // Draw both encoded and decoded image via deferredTextureImageData.
- SkImage::DeferredTextureImageUsageParams params;
- DrawDeferredTextureImageData(context, canvas, encodedImage.get(), &params, 0, 0);
- DrawDeferredTextureImageData(context, canvas, decodedImage.get(), &params, 10, 0);
-
- // Draw 50% scaled versions of the encoded and decoded images at medium quality.
- SkImage::DeferredTextureImageUsageParams mediumScaledParams;
- mediumScaledParams.fPreScaleMipLevel = 1;
- mediumScaledParams.fQuality = kMedium_SkFilterQuality;
-
- DrawDeferredTextureImageData(context, canvas, encodedImage.get(), &mediumScaledParams, 20, 0);
- DrawDeferredTextureImageData(context, canvas, decodedImage.get(), &mediumScaledParams, 30, 0);
-
- // Draw 50% scaled versions of the encoded and decoded images at none quality.
- SkImage::DeferredTextureImageUsageParams noneScaledParams;
- noneScaledParams.fPreScaleMipLevel = 1;
- noneScaledParams.fQuality = kNone_SkFilterQuality;
-
- DrawDeferredTextureImageData(context, canvas, encodedImage.get(), &noneScaledParams, 40, 0);
- DrawDeferredTextureImageData(context, canvas, decodedImage.get(), &noneScaledParams, 50, 0);
-}
-
-#endif
diff --git a/include/core/SkImage.h b/include/core/SkImage.h
index fd20e5e0e5..cc0f1f1655 100644
--- a/include/core/SkImage.h
+++ b/include/core/SkImage.h
@@ -396,7 +396,9 @@ public:
size_t getDeferredTextureImageData(const GrContextThreadSafeProxy&,
const DeferredTextureImageUsageParams[],
int paramCnt,
- void* buffer) const;
+ void* buffer,
+ SkSourceGammaTreatment treatment =
+ SkSourceGammaTreatment::kIgnore) const;
/**
* Returns a texture-backed image from data produced in SkImage::getDeferredTextureImageData.
@@ -469,7 +471,7 @@ protected:
private:
static sk_sp<SkImage> MakeTextureFromMipMap(GrContext*, const SkImageInfo&,
const GrMipLevel* texels, int mipLevelCount,
- SkBudgeted);
+ SkBudgeted, SkSourceGammaTreatment);
const int fWidth;
const int fHeight;
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index 2d434aee19..a6011875e8 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -395,6 +395,11 @@ sk_sp<SkImage> SkImage::MakeTextureFromPixmap(GrContext*, const SkPixmap&, SkBud
return nullptr;
}
+sk_sp<SkImage> MakeTextureFromMipMap(GrContext*, const SkImageInfo&, const GrMipLevel* texels,
+ int mipLevelCount, SkBudgeted, SkSourceGammaTreatment) {
+ return nullptr;
+}
+
sk_sp<SkImage> SkImage::MakeFromTexture(GrContext*, const GrBackendTextureDesc&, SkAlphaType,
sk_sp<SkColorSpace>, TextureReleaseProc, ReleaseContext) {
return nullptr;
@@ -402,7 +407,8 @@ sk_sp<SkImage> SkImage::MakeFromTexture(GrContext*, const GrBackendTextureDesc&,
size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy&,
const DeferredTextureImageUsageParams[],
- int paramCnt, void* buffer) const {
+ int paramCnt, void* buffer,
+ SkSourceGammaTreatment treatment) const {
return 0;
}
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index 44bb71c088..94fd8a3f3f 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -10,6 +10,7 @@
#include "GrContext.h"
#include "GrDrawContext.h"
#include "GrImageIDTextureAdjuster.h"
+#include "GrTexturePriv.h"
#include "effects/GrYUVEffect.h"
#include "SkCanvas.h"
#include "SkBitmapCache.h"
@@ -364,35 +365,60 @@ struct MipMapLevelData {
};
struct DeferredTextureImage {
- uint32_t fContextUniqueID;
+ uint32_t fContextUniqueID;
+ // Right now, the gamma treatment is only considered when generating mipmaps
+ SkSourceGammaTreatment fGammaTreatment;
// We don't store a SkImageInfo because it contains a ref-counted SkColorSpace.
- int fWidth;
- int fHeight;
- SkColorType fColorType;
- SkAlphaType fAlphaType;
- void* fColorSpace;
- size_t fColorSpaceSize;
- int fColorTableCnt;
- uint32_t* fColorTableData;
- int fMipMapLevelCount;
+ int fWidth;
+ int fHeight;
+ SkColorType fColorType;
+ SkAlphaType fAlphaType;
+ void* fColorSpace;
+ size_t fColorSpaceSize;
+ int fColorTableCnt;
+ uint32_t* fColorTableData;
+ int fMipMapLevelCount;
// The fMipMapLevelData array may contain more than 1 element.
// It contains fMipMapLevelCount elements.
// That means this struct's size is not known at compile-time.
- MipMapLevelData fMipMapLevelData[1];
+ MipMapLevelData fMipMapLevelData[1];
};
} // anonymous namespace
+static bool should_use_mip_maps(const SkImage::DeferredTextureImageUsageParams & param) {
+ bool shouldUseMipMaps = false;
+
+ // Use mipmaps if either
+ // 1.) it is a perspective matrix, or
+ // 2.) the quality is med/high and the scale is < 1
+ if (param.fMatrix.hasPerspective()) {
+ shouldUseMipMaps = true;
+ }
+ if (param.fQuality == kMedium_SkFilterQuality ||
+ param.fQuality == kHigh_SkFilterQuality) {
+ SkScalar minAxisScale = param.fMatrix.getMinScale();
+ if (minAxisScale != -1.f && minAxisScale < 1.f) {
+ shouldUseMipMaps = true;
+ }
+ }
+
+ return shouldUseMipMaps;
+}
+
size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& proxy,
const DeferredTextureImageUsageParams params[],
- int paramCnt, void* buffer) const {
+ int paramCnt, void* buffer,
+ SkSourceGammaTreatment gammaTreatment) const {
// Extract relevant min/max values from the params array.
int lowestPreScaleMipLevel = params[0].fPreScaleMipLevel;
SkFilterQuality highestFilterQuality = params[0].fQuality;
+ bool useMipMaps = should_use_mip_maps(params[0]);
for (int i = 1; i < paramCnt; ++i) {
if (lowestPreScaleMipLevel > params[i].fPreScaleMipLevel)
lowestPreScaleMipLevel = params[i].fPreScaleMipLevel;
if (highestFilterQuality < params[i].fQuality)
highestFilterQuality = params[i].fQuality;
+ useMipMaps |= should_use_mip_maps(params[i]);
}
const bool fillMode = SkToBool(buffer);
@@ -462,7 +488,29 @@ size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& prox
SkASSERT(!pixmap.ctable());
}
}
+ SkAlphaType at = this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
int mipMapLevelCount = 1;
+ if (useMipMaps) {
+ // SkMipMap only deals with the mipmap levels it generates, which does
+ // not include the base level.
+ // That means it generates and holds levels 1-x instead of 0-x.
+ // So the total mipmap level count is 1 more than what
+ // SkMipMap::ComputeLevelCount returns.
+ mipMapLevelCount = SkMipMap::ComputeLevelCount(scaledSize.width(), scaledSize.height()) + 1;
+
+ // We already initialized pixelSize to the size of the base level.
+ // SkMipMap will generate the extra mipmap levels. Their sizes need to
+ // be added to the total.
+ // Index 0 here does not refer to the base mipmap level -- it is
+ // SkMipMap's first generated mipmap level (level 1).
+ for (int currentMipMapLevelIndex = mipMapLevelCount - 1; currentMipMapLevelIndex >= 0;
+ currentMipMapLevelIndex--) {
+ SkISize mipSize = SkMipMap::ComputeLevelSize(scaledSize.width(), scaledSize.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;
@@ -496,6 +544,7 @@ size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& prox
SkASSERT(info == pixmap.info());
size_t rowBytes = pixmap.rowBytes();
DeferredTextureImage* dti = new (buffer) DeferredTextureImage();
+ dti->fGammaTreatment = gammaTreatment;
dti->fContextUniqueID = proxy.fContextUniqueID;
dti->fWidth = info.width();
dti->fHeight = info.height();
@@ -514,6 +563,32 @@ size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& prox
dti->fColorSpace = nullptr;
dti->fColorSpaceSize = 0;
}
+
+ // Fill in the mipmap levels if they exist
+ intptr_t mipLevelPtr = bufferAsInt + pixelOffset + SkAlign8(SkAutoPixmapStorage::AllocSize(
+ info, nullptr));
+ if (useMipMaps) {
+ SkAutoTDelete<SkMipMap> mipmaps(SkMipMap::Build(pixmap, gammaTreatment, nullptr));
+ // SkMipMap holds only the mipmap levels it generates.
+ // A programmer can use the data they provided to SkMipMap::Build as level 0.
+ // So the SkMipMap provides levels 1-x but it stores them in its own
+ // range 0-(x-1).
+ for (int generatedMipLevelIndex = 0; generatedMipLevelIndex < mipMapLevelCount - 1;
+ generatedMipLevelIndex++) {
+ SkISize mipSize = SkMipMap::ComputeLevelSize(scaledSize.width(), scaledSize.height(),
+ generatedMipLevelIndex);
+ SkImageInfo mipInfo = SkImageInfo::MakeN32(mipSize.fWidth, mipSize.fHeight, at);
+ SkMipMap::Level mipLevel;
+ mipmaps->getLevel(generatedMipLevelIndex, &mipLevel);
+ memcpy(reinterpret_cast<void*>(mipLevelPtr), mipLevel.fPixmap.addr(),
+ mipLevel.fPixmap.getSafeSize());
+ dti->fMipMapLevelData[generatedMipLevelIndex + 1].fPixelData =
+ reinterpret_cast<void*>(mipLevelPtr);
+ dti->fMipMapLevelData[generatedMipLevelIndex + 1].fRowBytes =
+ mipLevel.fPixmap.rowBytes();
+ mipLevelPtr += SkAlign8(mipLevel.fPixmap.getSafeSize());
+ }
+ }
return size;
}
@@ -532,17 +607,30 @@ sk_sp<SkImage> SkImage::MakeFromDeferredTextureImageData(GrContext* context, con
SkASSERT(dti->fColorTableData);
colorTable.reset(new SkColorTable(dti->fColorTableData, dti->fColorTableCnt));
}
- SkASSERT(dti->fMipMapLevelCount == 1);
+ int mipLevelCount = dti->fMipMapLevelCount;
+ SkASSERT(mipLevelCount >= 1);
sk_sp<SkColorSpace> colorSpace;
if (dti->fColorSpaceSize) {
colorSpace = SkColorSpace::Deserialize(dti->fColorSpace, dti->fColorSpaceSize);
}
SkImageInfo info = SkImageInfo::Make(dti->fWidth, dti->fHeight,
dti->fColorType, dti->fAlphaType, colorSpace);
- SkPixmap pixmap;
- pixmap.reset(info, dti->fMipMapLevelData[0].fPixelData,
- dti->fMipMapLevelData[0].fRowBytes, colorTable.get());
- return SkImage::MakeTextureFromPixmap(context, pixmap, budgeted);
+ if (mipLevelCount == 1) {
+ SkPixmap pixmap;
+ pixmap.reset(info, dti->fMipMapLevelData[0].fPixelData,
+ dti->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->fMipMapLevelData[i].fPixelData;
+ texels[i].fRowBytes = dti->fMipMapLevelData[i].fRowBytes;
+ }
+
+ return SkImage::MakeTextureFromMipMap(context, info, texels.get(),
+ mipLevelCount, SkBudgeted::kYes,
+ dti->fGammaTreatment);
+ }
}
///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -565,7 +653,8 @@ GrTexture* GrDeepCopyTexture(GrTexture* src, SkBudgeted budgeted) {
sk_sp<SkImage> SkImage::MakeTextureFromMipMap(GrContext* ctx, const SkImageInfo& info,
const GrMipLevel* texels, int mipLevelCount,
- SkBudgeted budgeted) {
+ SkBudgeted budgeted,
+ SkSourceGammaTreatment gammaTreatment) {
if (!ctx) {
return nullptr;
}
@@ -573,6 +662,7 @@ sk_sp<SkImage> SkImage::MakeTextureFromMipMap(GrContext* ctx, const SkImageInfo&
if (!texture) {
return nullptr;
}
+ texture->texturePriv().setGammaTreatment(gammaTreatment);
return sk_make_sp<SkImage_Gpu>(texture->width(), texture->height(), kNeedNewImageUniqueID,
info.alphaType(), texture, sk_ref_sp(info.colorSpace()),
budgeted);
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp
index ca4788c449..b24ded0fb3 100644
--- a/tests/ImageTest.cpp
+++ b/tests/ImageTest.cpp
@@ -921,8 +921,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DeferredTextureImage, reporter, ctxInfo) {
sk_sp<SkImage> image(testCase.fImageFactory());
size_t size = image->getDeferredTextureImageData(*proxy, testCase.fParams.data(),
static_cast<int>(testCase.fParams.size()),
- nullptr);
-
+ nullptr, SkSourceGammaTreatment::kIgnore);
static const char *const kFS[] = { "fail", "succeed" };
if (SkToBool(size) != testCase.fExpectation) {
ERRORF(reporter, "This image was expected to %s but did not.",
@@ -933,12 +932,12 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DeferredTextureImage, reporter, ctxInfo) {
void* misaligned = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(buffer) + 3);
if (image->getDeferredTextureImageData(*proxy, testCase.fParams.data(),
static_cast<int>(testCase.fParams.size()),
- misaligned)) {
+ misaligned, SkSourceGammaTreatment::kIgnore)) {
ERRORF(reporter, "Should fail when buffer is misaligned.");
}
if (!image->getDeferredTextureImageData(*proxy, testCase.fParams.data(),
static_cast<int>(testCase.fParams.size()),
- buffer)) {
+ buffer, SkSourceGammaTreatment::kIgnore)) {
ERRORF(reporter, "deferred image size succeeded but creation failed.");
} else {
for (auto budgeted : { SkBudgeted::kNo, SkBudgeted::kYes }) {