Use SkImageCacherator in SkImages
Possible follow-up changes to consider 1. Roll SkImage_Raster and _Gpu into _Generator, where the generator (or cacherator) is backed by a pre-existing texture or raster. 2. Evolve SkImageUsageType into a verb requiring stretching, and have the caller (common code) digest the caps() and usage, so that subclasses are just told what to do (stretch or not) 3. Common code/utility to convert an unstretched texture into a stretch one (and cache it) if the generator can only make an unstretched one. BUG=skia: Review URL: https://codereview.chromium.org/1282363002
This commit is contained in:
parent
e70afc9f48
commit
85d9178832
@ -249,6 +249,7 @@
|
|||||||
'<(skia_src_path)/doc/SkDocument.cpp',
|
'<(skia_src_path)/doc/SkDocument.cpp',
|
||||||
|
|
||||||
'<(skia_src_path)/image/SkImage.cpp',
|
'<(skia_src_path)/image/SkImage.cpp',
|
||||||
|
'<(skia_src_path)/image/SkImage_Generator.cpp',
|
||||||
# '<(skia_src_path)/image/SkImage_Gpu.cpp',
|
# '<(skia_src_path)/image/SkImage_Gpu.cpp',
|
||||||
'<(skia_src_path)/image/SkImage_Raster.cpp',
|
'<(skia_src_path)/image/SkImage_Raster.cpp',
|
||||||
'<(skia_src_path)/image/SkSurface.cpp',
|
'<(skia_src_path)/image/SkSurface.cpp',
|
||||||
|
@ -214,6 +214,11 @@ public:
|
|||||||
|
|
||||||
SkIRect bounds() const { return fInfo.bounds(); }
|
SkIRect bounds() const { return fInfo.bounds(); }
|
||||||
SkISize dimensions() const { return fInfo.dimensions(); }
|
SkISize dimensions() const { return fInfo.dimensions(); }
|
||||||
|
// Returns the bounds of this bitmap, offset by its pixelref origin.
|
||||||
|
SkIRect getSubset() const {
|
||||||
|
return SkIRect::MakeXYWH(fPixelRefOrigin.x(), fPixelRefOrigin.y(),
|
||||||
|
fInfo.width(), fInfo.height());
|
||||||
|
}
|
||||||
|
|
||||||
bool setInfo(const SkImageInfo&, size_t rowBytes = 0);
|
bool setInfo(const SkImageInfo&, size_t rowBytes = 0);
|
||||||
|
|
||||||
|
@ -150,6 +150,8 @@ public:
|
|||||||
|
|
||||||
int width() const { return fWidth; }
|
int width() const { return fWidth; }
|
||||||
int height() const { return fHeight; }
|
int height() const { return fHeight; }
|
||||||
|
SkISize dimensions() const { return SkISize::Make(fWidth, fHeight); }
|
||||||
|
SkIRect bounds() const { return SkIRect::MakeWH(fWidth, fHeight); }
|
||||||
uint32_t uniqueID() const { return fUniqueID; }
|
uint32_t uniqueID() const { return fUniqueID; }
|
||||||
virtual bool isOpaque() const { return false; }
|
virtual bool isOpaque() const { return false; }
|
||||||
|
|
||||||
|
@ -81,7 +81,10 @@ GrPixelConfig GrIsCompressedTextureDataSupported(GrContext* ctx, SkData* data,
|
|||||||
int expectedW, int expectedH,
|
int expectedW, int expectedH,
|
||||||
const void** outStartOfDataToUpload);
|
const void** outStartOfDataToUpload);
|
||||||
|
|
||||||
|
// Helper that calls GrIsImageInCache assuming bitmap is not volatile.
|
||||||
bool GrIsBitmapInCache(const GrContext*, const SkBitmap&, const GrTextureParams*);
|
bool GrIsBitmapInCache(const GrContext*, const SkBitmap&, const GrTextureParams*);
|
||||||
|
bool GrIsImageInCache(const GrContext* ctx, uint32_t imageID, const SkIRect& subset,
|
||||||
|
GrTexture* nativeTexture, const GrTextureParams*);
|
||||||
|
|
||||||
GrTexture* GrRefCachedBitmapTexture(GrContext*, const SkBitmap&, const GrTextureParams*);
|
GrTexture* GrRefCachedBitmapTexture(GrContext*, const SkBitmap&, const GrTextureParams*);
|
||||||
GrTexture* GrRefCachedBitmapTexture(GrContext*, const SkBitmap&, SkImageUsageType);
|
GrTexture* GrRefCachedBitmapTexture(GrContext*, const SkBitmap&, SkImageUsageType);
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "GrGpuResourcePriv.h"
|
#include "GrGpuResourcePriv.h"
|
||||||
#include "GrResourceKey.h"
|
#include "GrResourceKey.h"
|
||||||
#include "GrTextureAccess.h"
|
#include "GrTextureAccess.h"
|
||||||
|
#include "GrYUVProvider.h"
|
||||||
#include "SkGr.h"
|
#include "SkGr.h"
|
||||||
#include "SkGrPriv.h"
|
#include "SkGrPriv.h"
|
||||||
#endif
|
#endif
|
||||||
@ -158,6 +159,49 @@ bool SkImageCacherator::lockAsBitmap(SkBitmap* bitmap) {
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#if SK_SUPPORT_GPU
|
||||||
|
static void make_texture_desc(const SkImageInfo& info, GrSurfaceDesc* desc) {
|
||||||
|
desc->fFlags = kNone_GrSurfaceFlags;
|
||||||
|
desc->fWidth = info.width();
|
||||||
|
desc->fHeight = info.height();
|
||||||
|
desc->fConfig = SkImageInfo2GrPixelConfig(info);
|
||||||
|
desc->fSampleCnt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GrTexture* load_compressed_into_texture(GrContext* ctx, SkData* data, GrSurfaceDesc desc) {
|
||||||
|
const void* rawStart;
|
||||||
|
GrPixelConfig config = GrIsCompressedTextureDataSupported(ctx, data, desc.fWidth, desc.fHeight,
|
||||||
|
&rawStart);
|
||||||
|
if (kUnknown_GrPixelConfig == config) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
desc.fConfig = config;
|
||||||
|
return ctx->textureProvider()->createTexture(desc, true, rawStart, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Generator_GrYUVProvider : public GrYUVProvider {
|
||||||
|
SkImageGenerator* fGen;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Generator_GrYUVProvider(SkImageGenerator* gen) : fGen(gen) {}
|
||||||
|
|
||||||
|
uint32_t onGetID() override { return fGen->uniqueID(); }
|
||||||
|
bool onGetYUVSizes(SkISize sizes[3]) override {
|
||||||
|
return fGen->getYUV8Planes(sizes, nullptr, nullptr, nullptr);
|
||||||
|
}
|
||||||
|
bool onGetYUVPlanes(SkISize sizes[3], void* planes[3], size_t rowBytes[3],
|
||||||
|
SkYUVColorSpace* space) override {
|
||||||
|
return fGen->getYUV8Planes(sizes, planes, rowBytes, space);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static GrTexture* set_key_and_return(GrTexture* tex, const GrUniqueKey& key) {
|
||||||
|
tex->resourcePriv().setUniqueKey(key);
|
||||||
|
return tex;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have a 5 ways to try to return a texture (in sorted order)
|
* We have a 5 ways to try to return a texture (in sorted order)
|
||||||
*
|
*
|
||||||
@ -173,10 +217,19 @@ GrTexture* SkImageCacherator::lockAsTexture(GrContext* ctx, SkImageUsageType usa
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// textures (at least the texture-key) only support 16bit dimensions, so abort early
|
||||||
|
// if we're too big.
|
||||||
|
if (fInfo.width() > 0xFFFF || fInfo.height() > 0xFFFF) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
GrUniqueKey key;
|
GrUniqueKey key;
|
||||||
GrMakeKeyFromImageID(&key, fUniqueID, fInfo.width(), fInfo.height(), SkIPoint::Make(0, 0),
|
GrMakeKeyFromImageID(&key, fUniqueID, SkIRect::MakeWH(fInfo.width(), fInfo.height()),
|
||||||
*ctx->caps(), usage);
|
*ctx->caps(), usage);
|
||||||
|
|
||||||
|
GrSurfaceDesc desc;
|
||||||
|
make_texture_desc(fInfo, &desc);
|
||||||
|
|
||||||
// 1. Check the cache for a pre-existing one
|
// 1. Check the cache for a pre-existing one
|
||||||
if (GrTexture* tex = ctx->textureProvider()->findAndRefTextureByUniqueKey(key)) {
|
if (GrTexture* tex = ctx->textureProvider()->findAndRefTextureByUniqueKey(key)) {
|
||||||
return tex;
|
return tex;
|
||||||
@ -187,26 +240,36 @@ GrTexture* SkImageCacherator::lockAsTexture(GrContext* ctx, SkImageUsageType usa
|
|||||||
ScopedGenerator generator(this);
|
ScopedGenerator generator(this);
|
||||||
SkIRect subset = SkIRect::MakeXYWH(fOrigin.x(), fOrigin.y(), fInfo.width(), fInfo.height());
|
SkIRect subset = SkIRect::MakeXYWH(fOrigin.x(), fOrigin.y(), fInfo.width(), fInfo.height());
|
||||||
if (GrTexture* tex = generator->generateTexture(ctx, usage, &subset)) {
|
if (GrTexture* tex = generator->generateTexture(ctx, usage, &subset)) {
|
||||||
tex->resourcePriv().setUniqueKey(key);
|
return set_key_and_return(tex, key);
|
||||||
return tex;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Ask the generator to return a compressed form that the GPU might support
|
// 3. Ask the generator to return a compressed form that the GPU might support
|
||||||
// TODO
|
SkAutoTUnref<SkData> data(this->refEncoded());
|
||||||
|
if (data) {
|
||||||
|
GrTexture* tex = load_compressed_into_texture(ctx, data, desc);
|
||||||
|
if (tex) {
|
||||||
|
return set_key_and_return(tex, key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 4. Ask the generator to return YUV planes, which the GPU can convert
|
// 4. Ask the generator to return YUV planes, which the GPU can convert
|
||||||
// TODO
|
{
|
||||||
|
ScopedGenerator generator(this);
|
||||||
|
Generator_GrYUVProvider provider(generator);
|
||||||
|
GrTexture* tex = provider.refAsTexture(ctx, desc, true);
|
||||||
|
if (tex) {
|
||||||
|
return set_key_and_return(tex, key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 5. Ask the generator to return RGB(A) data, which the GPU can convert
|
// 5. Ask the generator to return RGB(A) data, which the GPU can convert
|
||||||
SkBitmap bitmap;
|
SkBitmap bitmap;
|
||||||
if (!this->generateBitmap(&bitmap)) {
|
if (this->generateBitmap(&bitmap)) {
|
||||||
return nullptr;
|
return GrRefCachedBitmapTexture(ctx, bitmap, usage);
|
||||||
}
|
}
|
||||||
return GrRefCachedBitmapTexture(ctx, bitmap, usage);
|
|
||||||
#else
|
|
||||||
return nullptr;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,7 +693,7 @@ static inline int get_tile_count(const SkIRect& srcRect, int tileSize) {
|
|||||||
return tilesX * tilesY;
|
return tilesX * tilesY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int determine_tile_size(const SkBitmap& bitmap, const SkIRect& src, int maxTileSize) {
|
static int determine_tile_size(const SkIRect& src, int maxTileSize) {
|
||||||
if (maxTileSize <= kBmpSmallTileSize) {
|
if (maxTileSize <= kBmpSmallTileSize) {
|
||||||
return maxTileSize;
|
return maxTileSize;
|
||||||
}
|
}
|
||||||
@ -716,7 +716,7 @@ static int determine_tile_size(const SkBitmap& bitmap, const SkIRect& src, int m
|
|||||||
static void determine_clipped_src_rect(const GrRenderTarget* rt,
|
static void determine_clipped_src_rect(const GrRenderTarget* rt,
|
||||||
const GrClip& clip,
|
const GrClip& clip,
|
||||||
const SkMatrix& viewMatrix,
|
const SkMatrix& viewMatrix,
|
||||||
const SkBitmap& bitmap,
|
const SkISize& imageSize,
|
||||||
const SkRect* srcRectPtr,
|
const SkRect* srcRectPtr,
|
||||||
SkIRect* clippedSrcIRect) {
|
SkIRect* clippedSrcIRect) {
|
||||||
clip.getConservativeBounds(rt, clippedSrcIRect, nullptr);
|
clip.getConservativeBounds(rt, clippedSrcIRect, nullptr);
|
||||||
@ -736,12 +736,61 @@ static void determine_clipped_src_rect(const GrRenderTarget* rt,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
clippedSrcRect.roundOut(clippedSrcIRect);
|
clippedSrcRect.roundOut(clippedSrcIRect);
|
||||||
SkIRect bmpBounds = SkIRect::MakeWH(bitmap.width(), bitmap.height());
|
SkIRect bmpBounds = SkIRect::MakeSize(imageSize);
|
||||||
if (!clippedSrcIRect->intersect(bmpBounds)) {
|
if (!clippedSrcIRect->intersect(bmpBounds)) {
|
||||||
clippedSrcIRect->setEmpty();
|
clippedSrcIRect->setEmpty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SkGpuDevice::shouldTileImageID(uint32_t imageID, const SkIRect& imageRect,
|
||||||
|
const SkMatrix& viewMatrix,
|
||||||
|
const GrTextureParams& params,
|
||||||
|
const SkRect* srcRectPtr,
|
||||||
|
int maxTileSize,
|
||||||
|
int* tileSize,
|
||||||
|
SkIRect* clippedSubset) const {
|
||||||
|
// if it's larger than the max tile size, then we have no choice but tiling.
|
||||||
|
if (imageRect.width() > maxTileSize || imageRect.height() > maxTileSize) {
|
||||||
|
determine_clipped_src_rect(fRenderTarget, fClip, viewMatrix, imageRect.size(),
|
||||||
|
srcRectPtr, clippedSubset);
|
||||||
|
*tileSize = determine_tile_size(*clippedSubset, maxTileSize);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t area = imageRect.width() * imageRect.height();
|
||||||
|
if (area < 4 * kBmpSmallTileSize * kBmpSmallTileSize) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the entire image/bitmap is already in our cache then no reason to tile it
|
||||||
|
if (GrIsImageInCache(fContext, imageID, imageRect, nullptr, ¶ms)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point we know we could do the draw by uploading the entire bitmap
|
||||||
|
// as a texture. However, if the texture would be large compared to the
|
||||||
|
// cache size and we don't require most of it for this draw then tile to
|
||||||
|
// reduce the amount of upload and cache spill.
|
||||||
|
|
||||||
|
// assumption here is that sw bitmap size is a good proxy for its size as
|
||||||
|
// a texture
|
||||||
|
size_t bmpSize = area * sizeof(SkPMColor); // assume 32bit pixels
|
||||||
|
size_t cacheSize;
|
||||||
|
fContext->getResourceCacheLimits(nullptr, &cacheSize);
|
||||||
|
if (bmpSize < cacheSize / 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Figure out how much of the src we will need based on the src rect and clipping.
|
||||||
|
determine_clipped_src_rect(fRenderTarget, fClip, viewMatrix, imageRect.size(), srcRectPtr,
|
||||||
|
clippedSubset);
|
||||||
|
*tileSize = kBmpSmallTileSize; // already know whole bitmap fits in one max sized tile.
|
||||||
|
size_t usedTileBytes = get_tile_count(*clippedSubset, kBmpSmallTileSize) *
|
||||||
|
kBmpSmallTileSize * kBmpSmallTileSize;
|
||||||
|
|
||||||
|
return usedTileBytes < 2 * bmpSize;
|
||||||
|
}
|
||||||
|
|
||||||
bool SkGpuDevice::shouldTileBitmap(const SkBitmap& bitmap,
|
bool SkGpuDevice::shouldTileBitmap(const SkBitmap& bitmap,
|
||||||
const SkMatrix& viewMatrix,
|
const SkMatrix& viewMatrix,
|
||||||
const GrTextureParams& params,
|
const GrTextureParams& params,
|
||||||
@ -754,45 +803,41 @@ bool SkGpuDevice::shouldTileBitmap(const SkBitmap& bitmap,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if it's larger than the max tile size, then we have no choice but tiling.
|
return this->shouldTileImageID(bitmap.getGenerationID(), bitmap.getSubset(), viewMatrix, params,
|
||||||
if (bitmap.width() > maxTileSize || bitmap.height() > maxTileSize) {
|
srcRectPtr, maxTileSize, tileSize, clippedSrcRect);
|
||||||
determine_clipped_src_rect(fRenderTarget, fClip, viewMatrix, bitmap,
|
}
|
||||||
srcRectPtr, clippedSrcRect);
|
|
||||||
*tileSize = determine_tile_size(bitmap, *clippedSrcRect, maxTileSize);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bitmap.width() * bitmap.height() < 4 * kBmpSmallTileSize * kBmpSmallTileSize) {
|
bool SkGpuDevice::shouldTileImage(const SkImage* image, const SkRect* srcRectPtr,
|
||||||
|
SkCanvas::SrcRectConstraint constraint, SkFilterQuality quality,
|
||||||
|
const SkMatrix& viewMatrix) const {
|
||||||
|
// if image is explictly texture backed then just use the texture
|
||||||
|
if (as_IB(image)->peekTexture()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the entire texture is already in our cache then no reason to tile it
|
GrTextureParams params;
|
||||||
if (GrIsBitmapInCache(fContext, bitmap, ¶ms)) {
|
bool doBicubic;
|
||||||
return false;
|
GrTextureParams::FilterMode textureFilterMode =
|
||||||
|
GrSkFilterQualityToGrFilterMode(quality, viewMatrix, SkMatrix::I(), &doBicubic);
|
||||||
|
|
||||||
|
int tileFilterPad;
|
||||||
|
if (doBicubic) {
|
||||||
|
tileFilterPad = GrBicubicEffect::kFilterTexelPad;
|
||||||
|
} else if (GrTextureParams::kNone_FilterMode == textureFilterMode) {
|
||||||
|
tileFilterPad = 0;
|
||||||
|
} else {
|
||||||
|
tileFilterPad = 1;
|
||||||
}
|
}
|
||||||
|
params.setFilterMode(textureFilterMode);
|
||||||
|
|
||||||
// At this point we know we could do the draw by uploading the entire bitmap
|
int maxTileSize = fContext->caps()->maxTextureSize() - 2 * tileFilterPad;
|
||||||
// as a texture. However, if the texture would be large compared to the
|
|
||||||
// cache size and we don't require most of it for this draw then tile to
|
|
||||||
// reduce the amount of upload and cache spill.
|
|
||||||
|
|
||||||
// assumption here is that sw bitmap size is a good proxy for its size as
|
// these are output, which we safely ignore, as we just want to know the predicate
|
||||||
// a texture
|
int outTileSize;
|
||||||
size_t bmpSize = bitmap.getSize();
|
SkIRect outClippedSrcRect;
|
||||||
size_t cacheSize;
|
|
||||||
fContext->getResourceCacheLimits(nullptr, &cacheSize);
|
|
||||||
if (bmpSize < cacheSize / 2) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Figure out how much of the src we will need based on the src rect and clipping.
|
return this->shouldTileImageID(image->unique(), image->bounds(), viewMatrix, params, srcRectPtr,
|
||||||
determine_clipped_src_rect(fRenderTarget, fClip, viewMatrix, bitmap, srcRectPtr,
|
maxTileSize, &outTileSize, &outClippedSrcRect);
|
||||||
clippedSrcRect);
|
|
||||||
*tileSize = kBmpSmallTileSize; // already know whole bitmap fits in one max sized tile.
|
|
||||||
size_t usedTileBytes = get_tile_count(*clippedSrcRect, kBmpSmallTileSize) *
|
|
||||||
kBmpSmallTileSize * kBmpSmallTileSize;
|
|
||||||
|
|
||||||
return usedTileBytes < 2 * bmpSize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkGpuDevice::drawBitmap(const SkDraw& origDraw,
|
void SkGpuDevice::drawBitmap(const SkDraw& origDraw,
|
||||||
@ -1090,11 +1135,9 @@ void SkGpuDevice::drawBitmapCommon(const SkDraw& draw,
|
|||||||
|
|
||||||
// If there is no mask filter than it is OK to handle the src rect -> dst rect scaling using
|
// If there is no mask filter than it is OK to handle the src rect -> dst rect scaling using
|
||||||
// the view matrix rather than a local matrix.
|
// the view matrix rather than a local matrix.
|
||||||
SkMatrix m;
|
|
||||||
m.setScale(dstSize.fWidth / srcRect.width(),
|
|
||||||
dstSize.fHeight / srcRect.height());
|
|
||||||
SkMatrix viewM = *draw.fMatrix;
|
SkMatrix viewM = *draw.fMatrix;
|
||||||
viewM.preConcat(m);
|
viewM.preScale(dstSize.fWidth / srcRect.width(),
|
||||||
|
dstSize.fHeight / srcRect.height());
|
||||||
|
|
||||||
GrTextureParams params;
|
GrTextureParams params;
|
||||||
bool doBicubic;
|
bool doBicubic;
|
||||||
@ -1546,8 +1589,8 @@ bool SkGpuDevice::filterImage(const SkImageFilter* filter, const SkBitmap& src,
|
|||||||
filter, ctx, result, offset);
|
filter, ctx, result, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool wrap_as_bm(const SkImage* image, SkBitmap* bm) {
|
static bool wrap_as_bm(GrContext* ctx, const SkImage* image, SkBitmap* bm) {
|
||||||
GrTexture* tex = as_IB(image)->getTexture();
|
SkAutoTUnref<GrTexture> tex(as_IB(image)->asTextureRef(ctx, kUntiled_SkImageUsageType));
|
||||||
if (tex) {
|
if (tex) {
|
||||||
GrWrapTextureInBitmap(tex, image->width(), image->height(), image->isOpaque(), bm);
|
GrWrapTextureInBitmap(tex, image->width(), image->height(), image->isOpaque(), bm);
|
||||||
return true;
|
return true;
|
||||||
@ -1559,18 +1602,47 @@ static bool wrap_as_bm(const SkImage* image, SkBitmap* bm) {
|
|||||||
void SkGpuDevice::drawImage(const SkDraw& draw, const SkImage* image, SkScalar x, SkScalar y,
|
void SkGpuDevice::drawImage(const SkDraw& draw, const SkImage* image, SkScalar x, SkScalar y,
|
||||||
const SkPaint& paint) {
|
const SkPaint& paint) {
|
||||||
SkBitmap bm;
|
SkBitmap bm;
|
||||||
if (wrap_as_bm(image, &bm)) {
|
if (GrTexture* tex = as_IB(image)->peekTexture()) {
|
||||||
this->drawBitmap(draw, bm, SkMatrix::MakeTrans(x, y), paint);
|
GrWrapTextureInBitmap(tex, image->width(), image->height(), image->isOpaque(), &bm);
|
||||||
|
} else {
|
||||||
|
if (this->shouldTileImage(image, nullptr, SkCanvas::kFast_SrcRectConstraint,
|
||||||
|
paint.getFilterQuality(), *draw.fMatrix)) {
|
||||||
|
// only support tiling as bitmap at the moment, so force raster-version
|
||||||
|
if (!as_IB(image)->getROPixels(&bm)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!wrap_as_bm(this->context(), image, &bm)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
this->drawBitmap(draw, bm, SkMatrix::MakeTrans(x, y), paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkGpuDevice::drawImageRect(const SkDraw& draw, const SkImage* image, const SkRect* src,
|
void SkGpuDevice::drawImageRect(const SkDraw& draw, const SkImage* image, const SkRect* src,
|
||||||
const SkRect& dst, const SkPaint& paint,
|
const SkRect& dst, const SkPaint& paint,
|
||||||
SkCanvas::SrcRectConstraint constraint) {
|
SkCanvas::SrcRectConstraint constraint) {
|
||||||
SkBitmap bm;
|
SkBitmap bm;
|
||||||
if (wrap_as_bm(image, &bm)) {
|
if (GrTexture* tex = as_IB(image)->peekTexture()) {
|
||||||
this->drawBitmapRect(draw, bm, src, dst, paint, constraint);
|
GrWrapTextureInBitmap(tex, image->width(), image->height(), image->isOpaque(), &bm);
|
||||||
|
} else {
|
||||||
|
SkMatrix viewMatrix = *draw.fMatrix;
|
||||||
|
viewMatrix.preScale(dst.width() / (src ? src->width() : image->width()),
|
||||||
|
dst.height() / (src ? src->height() : image->height()));
|
||||||
|
|
||||||
|
if (this->shouldTileImage(image, src, constraint, paint.getFilterQuality(), viewMatrix)) {
|
||||||
|
// only support tiling as bitmap at the moment, so force raster-version
|
||||||
|
if (!as_IB(image)->getROPixels(&bm)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!wrap_as_bm(this->context(), image, &bm)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
this->drawBitmapRect(draw, bm, src, dst, paint, constraint);
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -194,6 +194,13 @@ private:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// The tileSize and clippedSrcRect will be valid only if true is returned.
|
// The tileSize and clippedSrcRect will be valid only if true is returned.
|
||||||
|
bool shouldTileImageID(uint32_t imageID, const SkIRect& imageRect,
|
||||||
|
const SkMatrix& viewMatrix,
|
||||||
|
const GrTextureParams& params,
|
||||||
|
const SkRect* srcRectPtr,
|
||||||
|
int maxTileSize,
|
||||||
|
int* tileSize,
|
||||||
|
SkIRect* clippedSubset) const;
|
||||||
bool shouldTileBitmap(const SkBitmap& bitmap,
|
bool shouldTileBitmap(const SkBitmap& bitmap,
|
||||||
const SkMatrix& viewMatrix,
|
const SkMatrix& viewMatrix,
|
||||||
const GrTextureParams& sampler,
|
const GrTextureParams& sampler,
|
||||||
@ -201,6 +208,12 @@ private:
|
|||||||
int maxTileSize,
|
int maxTileSize,
|
||||||
int* tileSize,
|
int* tileSize,
|
||||||
SkIRect* clippedSrcRect) const;
|
SkIRect* clippedSrcRect) const;
|
||||||
|
// Just returns the predicate, not the out-tileSize or out-clippedSubset, as they are not
|
||||||
|
// needed at the moment.
|
||||||
|
bool shouldTileImage(const SkImage* image, const SkRect* srcRectPtr,
|
||||||
|
SkCanvas::SrcRectConstraint constraint, SkFilterQuality quality,
|
||||||
|
const SkMatrix& viewMatrix) const;
|
||||||
|
|
||||||
void internalDrawBitmap(const SkBitmap&,
|
void internalDrawBitmap(const SkBitmap&,
|
||||||
const SkMatrix& viewMatrix,
|
const SkMatrix& viewMatrix,
|
||||||
const SkRect&,
|
const SkRect&,
|
||||||
|
@ -155,21 +155,19 @@ static bool make_stretched_key(const GrUniqueKey& origKey, const Stretch& stretc
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void make_unstretched_key(GrUniqueKey* key, uint32_t imageID,
|
static void make_unstretched_key(GrUniqueKey* key, uint32_t imageID, const SkIRect& subset) {
|
||||||
U16CPU width, U16CPU height, SkIPoint origin) {
|
SkASSERT(SkIsU16(subset.width()));
|
||||||
SkASSERT((uint16_t)width == width);
|
SkASSERT(SkIsU16(subset.height()));
|
||||||
SkASSERT((uint16_t)height == height);
|
|
||||||
|
|
||||||
static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
|
static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
|
||||||
GrUniqueKey::Builder builder(key, kDomain, 4);
|
GrUniqueKey::Builder builder(key, kDomain, 4);
|
||||||
builder[0] = imageID;
|
builder[0] = imageID;
|
||||||
builder[1] = origin.fX;
|
builder[1] = subset.x();
|
||||||
builder[2] = origin.fY;
|
builder[2] = subset.y();
|
||||||
builder[3] = width | (height << 16);
|
builder[3] = subset.width() | (subset.height() << 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID,
|
void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& subset,
|
||||||
U16CPU width, U16CPU height, SkIPoint origin,
|
|
||||||
const GrCaps& caps, SkImageUsageType usage) {
|
const GrCaps& caps, SkImageUsageType usage) {
|
||||||
const Stretch::Type stretches[] = {
|
const Stretch::Type stretches[] = {
|
||||||
Stretch::kNone_Type, // kUntiled_SkImageUsageType
|
Stretch::kNone_Type, // kUntiled_SkImageUsageType
|
||||||
@ -177,38 +175,31 @@ void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID,
|
|||||||
Stretch::kBilerp_Type, // kTiled_Filtered_SkImageUsageType
|
Stretch::kBilerp_Type, // kTiled_Filtered_SkImageUsageType
|
||||||
};
|
};
|
||||||
|
|
||||||
const bool isPow2 = SkIsPow2(width) && SkIsPow2(height);
|
const bool isPow2 = SkIsPow2(subset.width()) && SkIsPow2(subset.height());
|
||||||
const bool needToStretch = !isPow2 &&
|
const bool needToStretch = !isPow2 &&
|
||||||
usage != kUntiled_SkImageUsageType &&
|
usage != kUntiled_SkImageUsageType &&
|
||||||
!caps.npotTextureTileSupport();
|
!caps.npotTextureTileSupport();
|
||||||
|
|
||||||
if (needToStretch) {
|
if (needToStretch) {
|
||||||
GrUniqueKey tmpKey;
|
GrUniqueKey tmpKey;
|
||||||
make_unstretched_key(&tmpKey, imageID, width, height, origin);
|
make_unstretched_key(&tmpKey, imageID, subset);
|
||||||
|
|
||||||
Stretch stretch;
|
Stretch stretch;
|
||||||
stretch.fType = stretches[usage];
|
stretch.fType = stretches[usage];
|
||||||
stretch.fWidth = SkNextPow2(width);
|
stretch.fWidth = SkNextPow2(subset.width());
|
||||||
stretch.fHeight = SkNextPow2(height);
|
stretch.fHeight = SkNextPow2(subset.height());
|
||||||
if (!make_stretched_key(tmpKey, stretch, key)) {
|
if (!make_stretched_key(tmpKey, stretch, key)) {
|
||||||
goto UNSTRETCHED;
|
goto UNSTRETCHED;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
UNSTRETCHED:
|
UNSTRETCHED:
|
||||||
make_unstretched_key(key, imageID, width, height, origin);
|
make_unstretched_key(key, imageID, subset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void make_unstretched_key(const SkBitmap& bitmap, GrUniqueKey* key) {
|
static void make_image_keys(uint32_t imageID, const SkIRect& subset, const Stretch& stretch,
|
||||||
make_unstretched_key(key, bitmap.getGenerationID(), bitmap.width(), bitmap.height(),
|
GrUniqueKey* key, GrUniqueKey* stretchedKey) {
|
||||||
bitmap.pixelRefOrigin());
|
make_unstretched_key(key, imageID, subset);
|
||||||
}
|
|
||||||
|
|
||||||
static void make_bitmap_keys(const SkBitmap& bitmap,
|
|
||||||
const Stretch& stretch,
|
|
||||||
GrUniqueKey* key,
|
|
||||||
GrUniqueKey* stretchedKey) {
|
|
||||||
make_unstretched_key(bitmap, key);
|
|
||||||
if (Stretch::kNone_Type != stretch.fType) {
|
if (Stretch::kNone_Type != stretch.fType) {
|
||||||
make_stretched_key(*key, stretch, stretchedKey);
|
make_stretched_key(*key, stretch, stretchedKey);
|
||||||
}
|
}
|
||||||
@ -534,23 +525,17 @@ static GrTexture* create_bitmap_texture(GrContext* ctx,
|
|||||||
return create_unstretched_bitmap_texture(ctx, bmp, unstretchedKey);
|
return create_unstretched_bitmap_texture(ctx, bmp, unstretchedKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GrIsBitmapInCache(const GrContext* ctx,
|
bool GrIsImageInCache(const GrContext* ctx, uint32_t imageID, const SkIRect& subset,
|
||||||
const SkBitmap& bitmap,
|
GrTexture* nativeTexture, const GrTextureParams* params) {
|
||||||
const GrTextureParams* params) {
|
|
||||||
Stretch stretch;
|
Stretch stretch;
|
||||||
get_stretch(ctx, bitmap.width(), bitmap.height(), params, &stretch);
|
get_stretch(ctx, subset.width(), subset.height(), params, &stretch);
|
||||||
|
|
||||||
// Handle the case where the bitmap is explicitly texture backed.
|
// Handle the case where the bitmap/image is explicitly texture backed.
|
||||||
GrTexture* texture = bitmap.getTexture();
|
if (nativeTexture) {
|
||||||
if (texture) {
|
|
||||||
if (Stretch::kNone_Type == stretch.fType) {
|
if (Stretch::kNone_Type == stretch.fType) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// No keys for volatile bitmaps.
|
const GrUniqueKey& key = nativeTexture->getUniqueKey();
|
||||||
if (bitmap.isVolatile()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const GrUniqueKey& key = texture->getUniqueKey();
|
|
||||||
if (!key.isValid()) {
|
if (!key.isValid()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -559,17 +544,21 @@ bool GrIsBitmapInCache(const GrContext* ctx,
|
|||||||
return ctx->textureProvider()->existsTextureWithUniqueKey(stretchedKey);
|
return ctx->textureProvider()->existsTextureWithUniqueKey(stretchedKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't cache volatile bitmaps
|
|
||||||
if (bitmap.isVolatile()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
GrUniqueKey key, stretchedKey;
|
GrUniqueKey key, stretchedKey;
|
||||||
make_bitmap_keys(bitmap, stretch, &key, &stretchedKey);
|
make_image_keys(imageID, subset, stretch, &key, &stretchedKey);
|
||||||
return ctx->textureProvider()->existsTextureWithUniqueKey(
|
return ctx->textureProvider()->existsTextureWithUniqueKey(
|
||||||
(Stretch::kNone_Type == stretch.fType) ? key : stretchedKey);
|
(Stretch::kNone_Type == stretch.fType) ? key : stretchedKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GrIsBitmapInCache(const GrContext* ctx, const SkBitmap& bitmap,
|
||||||
|
const GrTextureParams* params) {
|
||||||
|
if (bitmap.isVolatile()) {
|
||||||
|
return false; // we don't cache volatile bitmaps.
|
||||||
|
}
|
||||||
|
return GrIsImageInCache(ctx, bitmap.getGenerationID(), bitmap.getSubset(), bitmap.getTexture(),
|
||||||
|
params);
|
||||||
|
}
|
||||||
|
|
||||||
GrTexture* GrRefCachedBitmapTexture(GrContext* ctx,
|
GrTexture* GrRefCachedBitmapTexture(GrContext* ctx,
|
||||||
const SkBitmap& bitmap,
|
const SkBitmap& bitmap,
|
||||||
const GrTextureParams* params) {
|
const GrTextureParams* params) {
|
||||||
@ -602,7 +591,7 @@ GrTexture* GrRefCachedBitmapTexture(GrContext* ctx,
|
|||||||
|
|
||||||
if (!bitmap.isVolatile()) {
|
if (!bitmap.isVolatile()) {
|
||||||
// If the bitmap isn't changing try to find a cached copy first.
|
// If the bitmap isn't changing try to find a cached copy first.
|
||||||
make_bitmap_keys(bitmap, stretch, &key, &resizedKey);
|
make_image_keys(bitmap.getGenerationID(), bitmap.getSubset(), stretch, &key, &resizedKey);
|
||||||
|
|
||||||
result = ctx->textureProvider()->findAndRefTextureByUniqueKey(
|
result = ctx->textureProvider()->findAndRefTextureByUniqueKey(
|
||||||
resizedKey.isValid() ? resizedKey : key);
|
resizedKey.isValid() ? resizedKey : key);
|
||||||
|
@ -25,8 +25,7 @@ class GrUniqueKey;
|
|||||||
*
|
*
|
||||||
* Note: width/height must fit in 16bits for this impl.
|
* Note: width/height must fit in 16bits for this impl.
|
||||||
*/
|
*/
|
||||||
void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID,
|
void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& imageBounds,
|
||||||
U16CPU width, U16CPU height, SkIPoint origin,
|
|
||||||
const GrCaps&, SkImageUsageType);
|
const GrCaps&, SkImageUsageType);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -158,7 +158,7 @@ SkImage* SkImage::newImage(int newWidth, int newHeight, const SkIRect* subset,
|
|||||||
#if SK_SUPPORT_GPU
|
#if SK_SUPPORT_GPU
|
||||||
|
|
||||||
GrTexture* SkImage::getTexture() const {
|
GrTexture* SkImage::getTexture() const {
|
||||||
return as_IB(this)->getTexture();
|
return as_IB(this)->peekTexture();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkImage::isTextureBacked() const { return SkToBool(as_IB(this)->getTexture()); }
|
bool SkImage::isTextureBacked() const { return SkToBool(as_IB(this)->getTexture()); }
|
||||||
|
@ -54,7 +54,7 @@ public:
|
|||||||
|
|
||||||
virtual void onPreroll(GrContext*) const {}
|
virtual void onPreroll(GrContext*) const {}
|
||||||
|
|
||||||
virtual GrTexture* getTexture() const { return nullptr; }
|
virtual GrTexture* peekTexture() const { return nullptr; }
|
||||||
|
|
||||||
// return a read-only copy of the pixels. We promise to not modify them,
|
// return a read-only copy of the pixels. We promise to not modify them,
|
||||||
// but only inspect them (or encode them).
|
// but only inspect them (or encode them).
|
||||||
@ -73,6 +73,9 @@ public:
|
|||||||
|
|
||||||
virtual bool onIsLazyGenerated() const { return false; }
|
virtual bool onIsLazyGenerated() const { return false; }
|
||||||
|
|
||||||
|
// Caller must call unref when they are done.
|
||||||
|
virtual GrTexture* asTextureRef(GrContext*, SkImageUsageType) const { return nullptr; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const SkSurfaceProps fProps;
|
const SkSurfaceProps fProps;
|
||||||
|
|
||||||
|
95
src/image/SkImage_Generator.cpp
Normal file
95
src/image/SkImage_Generator.cpp
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015 Google Inc.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
|
* found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SkImage_Base.h"
|
||||||
|
#include "SkBitmap.h"
|
||||||
|
#include "SkData.h"
|
||||||
|
#include "SkImageCacherator.h"
|
||||||
|
#include "SkImagePriv.h"
|
||||||
|
#include "SkPixelRef.h"
|
||||||
|
#include "SkSurface.h"
|
||||||
|
|
||||||
|
class SkImage_Generator : public SkImage_Base {
|
||||||
|
public:
|
||||||
|
SkImage_Generator(SkImageCacherator* cache)
|
||||||
|
: INHERITED(cache->info().width(), cache->info().height(), kNeedNewImageUniqueID, NULL)
|
||||||
|
, fCache(cache) // take ownership
|
||||||
|
{}
|
||||||
|
|
||||||
|
SkSurface* onNewSurface(const SkImageInfo&, const SkSurfaceProps&) const override;
|
||||||
|
bool onReadPixels(const SkImageInfo&, void*, size_t, int srcX, int srcY) const override;
|
||||||
|
const void* onPeekPixels(SkImageInfo*, size_t* /*rowBytes*/) const override;
|
||||||
|
SkData* onRefEncoded() const override;
|
||||||
|
bool isOpaque() const override { return fCache->info().isOpaque(); }
|
||||||
|
|
||||||
|
bool getROPixels(SkBitmap*) const override;
|
||||||
|
GrTexture* asTextureRef(GrContext*, SkImageUsageType) const override;
|
||||||
|
|
||||||
|
SkShader* onNewShader(SkShader::TileMode,
|
||||||
|
SkShader::TileMode,
|
||||||
|
const SkMatrix* localMatrix) const override;
|
||||||
|
|
||||||
|
bool onIsLazyGenerated() const override { return true; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
SkAutoTDelete<SkImageCacherator> fCache;
|
||||||
|
|
||||||
|
typedef SkImage_Base INHERITED;
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
SkShader* SkImage_Generator::onNewShader(SkShader::TileMode tileX, SkShader::TileMode tileY,
|
||||||
|
const SkMatrix* localMatrix) const {
|
||||||
|
// TODO: need a native Shader that takes Cacherator (or this image) so we can natively return
|
||||||
|
// textures as output from the shader.
|
||||||
|
SkBitmap bm;
|
||||||
|
if (this->getROPixels(&bm)) {
|
||||||
|
return SkShader::CreateBitmapShader(bm, tileX, tileY, localMatrix);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
SkSurface* SkImage_Generator::onNewSurface(const SkImageInfo& info,
|
||||||
|
const SkSurfaceProps& props) const {
|
||||||
|
return SkSurface::NewRaster(info, &props);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SkImage_Generator::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
|
||||||
|
int srcX, int srcY) const {
|
||||||
|
SkBitmap bm;
|
||||||
|
if (this->getROPixels(&bm)) {
|
||||||
|
return bm.readPixels(dstInfo, dstPixels, dstRB, srcX, srcY);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const void* SkImage_Generator::onPeekPixels(SkImageInfo* infoPtr, size_t* rowBytesPtr) const {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SkData* SkImage_Generator::onRefEncoded() const {
|
||||||
|
return fCache->refEncoded();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SkImage_Generator::getROPixels(SkBitmap* bitmap) const {
|
||||||
|
return fCache->lockAsBitmap(bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
GrTexture* SkImage_Generator::asTextureRef(GrContext* ctx, SkImageUsageType usage) const {
|
||||||
|
return fCache->lockAsTexture(ctx, usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef SK_SUPPORT_LEGACY_NEWFROMGENERATOR
|
||||||
|
SkImage* SkImage::NewFromGenerator(SkImageGenerator* generator, const SkIRect* subset) {
|
||||||
|
SkImageCacherator* cache = SkImageCacherator::NewFromGenerator(generator, subset);
|
||||||
|
if (!cache) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return SkNEW_ARGS(SkImage_Generator, (cache));
|
||||||
|
}
|
||||||
|
#endif
|
@ -79,6 +79,11 @@ bool SkImage_Gpu::getROPixels(SkBitmap* dst) const {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GrTexture* SkImage_Gpu::asTextureRef(GrContext* ctx, SkImageUsageType usage) const {
|
||||||
|
fTexture->ref();
|
||||||
|
return fTexture;
|
||||||
|
}
|
||||||
|
|
||||||
bool SkImage_Gpu::isOpaque() const {
|
bool SkImage_Gpu::isOpaque() const {
|
||||||
return GrPixelConfigIsOpaque(fTexture->config()) || fAlphaType == kOpaque_SkAlphaType;
|
return GrPixelConfigIsOpaque(fTexture->config()) || fAlphaType == kOpaque_SkAlphaType;
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool getROPixels(SkBitmap*) const override;
|
bool getROPixels(SkBitmap*) const override;
|
||||||
GrTexture* getTexture() const override { return fTexture; }
|
GrTexture* asTextureRef(GrContext* ctx, SkImageUsageType usage) const override;
|
||||||
|
|
||||||
|
GrTexture* peekTexture() const override { return fTexture; }
|
||||||
SkShader* onNewShader(SkShader::TileMode,
|
SkShader* onNewShader(SkShader::TileMode,
|
||||||
SkShader::TileMode,
|
SkShader::TileMode,
|
||||||
const SkMatrix* localMatrix) const override;
|
const SkMatrix* localMatrix) const override;
|
||||||
|
@ -231,18 +231,6 @@ SkImage* SkImage::NewFromRaster(const SkImageInfo& info, const void* pixels, siz
|
|||||||
return new SkImage_Raster(info, data, rowBytes, ctable, nullptr);
|
return new SkImage_Raster(info, data, rowBytes, ctable, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SkImage* SkImage::NewFromGenerator(SkImageGenerator* generator, const SkIRect* subset) {
|
|
||||||
SkBitmap bitmap;
|
|
||||||
if (!SkInstallDiscardablePixelRef(generator, subset, &bitmap, nullptr)) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
if (0 == bitmap.width() || 0 == bitmap.height()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SkImage_Raster(bitmap, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
SkImage* SkNewImageFromPixelRef(const SkImageInfo& info, SkPixelRef* pr,
|
SkImage* SkNewImageFromPixelRef(const SkImageInfo& info, SkPixelRef* pr,
|
||||||
const SkIPoint& pixelRefOrigin, size_t rowBytes,
|
const SkIPoint& pixelRefOrigin, size_t rowBytes,
|
||||||
const SkSurfaceProps* props) {
|
const SkSurfaceProps* props) {
|
||||||
@ -301,3 +289,16 @@ bool SkImage_Raster::onAsLegacyBitmap(SkBitmap* bitmap, LegacyBitmapMode mode) c
|
|||||||
}
|
}
|
||||||
return this->INHERITED::onAsLegacyBitmap(bitmap, mode);
|
return this->INHERITED::onAsLegacyBitmap(bitmap, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SK_SUPPORT_LEGACY_NEWFROMGENERATOR
|
||||||
|
SkImage* SkImage::NewFromGenerator(SkImageGenerator* generator, const SkIRect* subset) {
|
||||||
|
SkBitmap bitmap;
|
||||||
|
if (!SkInstallDiscardablePixelRef(generator, subset, &bitmap, nullptr)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (0 == bitmap.width() || 0 == bitmap.height()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return new SkImage_Raster(bitmap, nullptr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user