Stretch small textures up to 16 pixels on PowerVR 54x

Review URL: https://codereview.chromium.org/1161183002
This commit is contained in:
bsalomon 2015-06-01 07:13:42 -07:00 committed by Commit bot
parent c58e5326bb
commit c59a1df655
5 changed files with 85 additions and 44 deletions

View File

@ -180,6 +180,9 @@ public:
int maxRenderTargetSize() const { return fMaxRenderTargetSize; }
int maxTextureSize() const { return fMaxTextureSize; }
/** 0 unless GPU has problems with small textures */
int minTextureSize() const { return fMinTextureSize; }
// Will be 0 if MSAA is not supported
int maxSampleCount() const { return fMaxSampleCount; }
@ -229,6 +232,7 @@ protected:
int fMaxRenderTargetSize;
int fMaxTextureSize;
int fMinTextureSize;
int fMaxSampleCount;
// The first entry for each config is without msaa and the second is with.

View File

@ -15,6 +15,7 @@ struct GrContextOptions {
: fDrawPathToCompressedTexture(false)
, fSuppressPrints(false)
, fMaxTextureSizeOverride(SK_MaxS32)
, fMinTextureSizeOverride(0)
, fSuppressDualSourceBlending(false)
, fGeometryBufferMapThreshold(1 << 15) {}
@ -31,6 +32,7 @@ struct GrContextOptions {
detected values. */
int fMaxTextureSizeOverride;
int fMinTextureSizeOverride;
bool fSuppressDualSourceBlending;
/** fGeometryBufferMapThreshold gives a threshold (in bytes) for when Gr should

View File

@ -98,6 +98,7 @@ GrCaps::GrCaps(const GrContextOptions& options) {
fMaxRenderTargetSize = 0;
fMaxTextureSize = 0;
fMinTextureSize = 0;
fMaxSampleCount = 0;
memset(fConfigRenderSupport, 0, sizeof(fConfigRenderSupport));
@ -110,6 +111,7 @@ GrCaps::GrCaps(const GrContextOptions& options) {
void GrCaps::applyOptionsOverrides(const GrContextOptions& options) {
fMaxTextureSize = SkTMin(fMaxTextureSize, options.fMaxTextureSizeOverride);
fMinTextureSize = SkTMax(fMinTextureSize, options.fMinTextureSizeOverride);
}
static SkString map_flags_to_string(uint32_t flags) {
@ -148,6 +150,7 @@ SkString GrCaps::dump() const {
r.appendf("Draw Instead of Clear [workaround] : %s\n", gNY[fUseDrawInsteadOfClear]);
r.appendf("Max Texture Size : %d\n", fMaxTextureSize);
r.appendf("Min Texture Size : %d\n", fMinTextureSize);
r.appendf("Max Render Target Size : %d\n", fMaxRenderTargetSize);
r.appendf("Max Sample Count : %d\n", fMaxSampleCount);

View File

@ -88,34 +88,59 @@ static void build_index8_data(void* buffer, const SkBitmap& bitmap) {
////////////////////////////////////////////////////////////////////////////////
enum Stretch {
kNo_Stretch,
kBilerp_Stretch,
kNearest_Stretch
struct Stretch {
enum Type {
kNone_Type,
kBilerp_Type,
kNearest_Type
} fType;
int fWidth;
int fHeight;
};
static Stretch get_stretch_type(const GrContext* ctx, int width, int height,
const GrTextureParams* params) {
if (params && params->isTiled()) {
if (!ctx->caps()->npotTextureTileSupport() && (!SkIsPow2(width) || !SkIsPow2(height))) {
switch(params->filterMode()) {
case GrTextureParams::kNone_FilterMode:
return kNearest_Stretch;
case GrTextureParams::kBilerp_FilterMode:
case GrTextureParams::kMipMap_FilterMode:
return kBilerp_Stretch;
}
}
static void get_stretch(const GrContext* ctx, int width, int height,
const GrTextureParams* params, Stretch* stretch) {
stretch->fType = Stretch::kNone_Type;
bool doStretch = false;
if (params && params->isTiled() && !ctx->caps()->npotTextureTileSupport() &&
(!SkIsPow2(width) || !SkIsPow2(height))) {
doStretch = true;
stretch->fWidth = GrNextPow2(width);
stretch->fHeight = GrNextPow2(height);
} else if (width < ctx->caps()->minTextureSize() ||
height < ctx->caps()->minTextureSize()) {
// The small texture issues appear to be with tiling. Hence it seems ok to scale them
// up using the GPU. If issues persist we may need to CPU-stretch.
doStretch = true;
stretch->fWidth = SkTMax(width, ctx->caps()->minTextureSize());
stretch->fHeight = SkTMax(height, ctx->caps()->minTextureSize());
}
if (doStretch) {
switch(params->filterMode()) {
case GrTextureParams::kNone_FilterMode:
stretch->fType = Stretch::kNearest_Type;
break;
case GrTextureParams::kBilerp_FilterMode:
case GrTextureParams::kMipMap_FilterMode:
stretch->fType = Stretch::kBilerp_Type;
break;
}
} else {
stretch->fWidth = -1;
stretch->fHeight = -1;
stretch->fType = Stretch::kNone_Type;
}
return kNo_Stretch;
}
static bool make_stretched_key(const GrUniqueKey& origKey, Stretch stretch,
static bool make_stretched_key(const GrUniqueKey& origKey, const Stretch& stretch,
GrUniqueKey* stretchedKey) {
if (origKey.isValid() && kNo_Stretch != stretch) {
if (origKey.isValid() && Stretch::kNone_Type != stretch.fType) {
uint32_t width = SkToU16(stretch.fWidth);
uint32_t height = SkToU16(stretch.fHeight);
static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
GrUniqueKey::Builder builder(stretchedKey, origKey, kDomain, 1);
builder[0] = stretch;
GrUniqueKey::Builder builder(stretchedKey, origKey, kDomain, 3);
builder[0] = stretch.fType;
builder[1] = width | (height << 16);
builder.finish();
return true;
}
@ -140,11 +165,11 @@ static void make_unstretched_key(const SkBitmap& bitmap, GrUniqueKey* key) {
}
static void make_bitmap_keys(const SkBitmap& bitmap,
Stretch stretch,
const Stretch& stretch,
GrUniqueKey* key,
GrUniqueKey* stretchedKey) {
make_unstretched_key(bitmap, key);
if (kNo_Stretch != stretch) {
if (Stretch::kNone_Type != stretch.fType) {
make_stretched_key(*key, stretch, stretchedKey);
}
}
@ -189,13 +214,13 @@ static GrTexture* create_texture_for_bmp(GrContext* ctx,
return result;
}
// creates a new texture that is the input texture scaled up to the next power of two in
// width or height. If optionalKey is valid it will be set on the new texture. stretch
// controls whether the scaling is done using nearest or bilerp filtering.
GrTexture* stretch_texture_to_next_pot(GrTexture* inputTexture, Stretch stretch,
SkPixelRef* pixelRef,
const GrUniqueKey& optionalKey) {
SkASSERT(kNo_Stretch != stretch);
// creates a new texture that is the input texture scaled up. If optionalKey is valid it will be
// set on the new texture. stretch controls whether the scaling is done using nearest or bilerp
// filtering and the size to stretch the texture to.
GrTexture* stretch_texture(GrTexture* inputTexture, const Stretch& stretch,
SkPixelRef* pixelRef,
const GrUniqueKey& optionalKey) {
SkASSERT(Stretch::kNone_Type != stretch.fType);
GrContext* context = inputTexture->getContext();
SkASSERT(context);
@ -204,8 +229,8 @@ GrTexture* stretch_texture_to_next_pot(GrTexture* inputTexture, Stretch stretch,
// Either it's a cache miss or the original wasn't cached to begin with.
GrSurfaceDesc rtDesc = inputTexture->desc();
rtDesc.fFlags = rtDesc.fFlags | kRenderTarget_GrSurfaceFlag;
rtDesc.fWidth = GrNextPow2(rtDesc.fWidth);
rtDesc.fHeight = GrNextPow2(rtDesc.fHeight);
rtDesc.fWidth = stretch.fWidth;
rtDesc.fHeight = stretch.fHeight;
rtDesc.fConfig = GrMakePixelConfigUncompressed(rtDesc.fConfig);
// If the config isn't renderable try converting to either A8 or an 32 bit config. Otherwise,
@ -241,8 +266,9 @@ GrTexture* stretch_texture_to_next_pot(GrTexture* inputTexture, Stretch stretch,
// If filtering is not desired then we want to ensure all texels in the resampled image are
// copies of texels from the original.
GrTextureParams params(SkShader::kClamp_TileMode,
kBilerp_Stretch == stretch ? GrTextureParams::kBilerp_FilterMode :
GrTextureParams::kNone_FilterMode);
Stretch::kBilerp_Type == stretch.fType ?
GrTextureParams::kBilerp_FilterMode :
GrTextureParams::kNone_FilterMode);
paint.addColorTextureProcessor(inputTexture, SkMatrix::I(), params);
SkRect rect = SkRect::MakeWH(SkIntToScalar(rtDesc.fWidth), SkIntToScalar(rtDesc.fHeight));
@ -479,10 +505,10 @@ static GrTexture* create_unstretched_bitmap_texture(GrContext* ctx,
static GrTexture* create_bitmap_texture(GrContext* ctx,
const SkBitmap& bmp,
Stretch stretch,
const Stretch& stretch,
const GrUniqueKey& unstretchedKey,
const GrUniqueKey& stretchedKey) {
if (kNo_Stretch != stretch) {
if (Stretch::kNone_Type != stretch.fType) {
SkAutoTUnref<GrTexture> unstretched;
// Check if we have the unstretched version in the cache, if not create it.
if (unstretchedKey.isValid()) {
@ -494,8 +520,7 @@ static GrTexture* create_bitmap_texture(GrContext* ctx,
return NULL;
}
}
GrTexture* stretched = stretch_texture_to_next_pot(unstretched, stretch, bmp.pixelRef(),
stretchedKey);
GrTexture* stretched = stretch_texture(unstretched, stretch, bmp.pixelRef(), stretchedKey);
return stretched;
}
@ -506,12 +531,13 @@ static GrTexture* create_bitmap_texture(GrContext* ctx,
bool GrIsBitmapInCache(const GrContext* ctx,
const SkBitmap& bitmap,
const GrTextureParams* params) {
Stretch stretch = get_stretch_type(ctx, bitmap.width(), bitmap.height(), params);
Stretch stretch;
get_stretch(ctx, bitmap.width(), bitmap.height(), params, &stretch);
// Handle the case where the bitmap is explicitly texture backed.
GrTexture* texture = bitmap.getTexture();
if (texture) {
if (kNo_Stretch == stretch) {
if (Stretch::kNone_Type == stretch.fType) {
return true;
}
// No keys for volatile bitmaps.
@ -535,18 +561,19 @@ bool GrIsBitmapInCache(const GrContext* ctx,
GrUniqueKey key, stretchedKey;
make_bitmap_keys(bitmap, stretch, &key, &stretchedKey);
return ctx->textureProvider()->existsTextureWithUniqueKey(
(kNo_Stretch == stretch) ? key : stretchedKey);
(Stretch::kNone_Type == stretch.fType) ? key : stretchedKey);
}
GrTexture* GrRefCachedBitmapTexture(GrContext* ctx,
const SkBitmap& bitmap,
const GrTextureParams* params) {
Stretch stretch = get_stretch_type(ctx, bitmap.width(), bitmap.height(), params);
Stretch stretch;
get_stretch(ctx, bitmap.width(), bitmap.height(), params, &stretch);
GrTexture* result = bitmap.getTexture();
if (result) {
if (kNo_Stretch == stretch) {
if (Stretch::kNone_Type == stretch.fType) {
return SkRef(result);
}
GrUniqueKey stretchedKey;
@ -562,7 +589,7 @@ GrTexture* GrRefCachedBitmapTexture(GrContext* ctx,
}
}
}
return stretch_texture_to_next_pot(result, stretch, bitmap.pixelRef(), stretchedKey);
return stretch_texture(result, stretch, bitmap.pixelRef(), stretchedKey);
}
GrUniqueKey key, resizedKey;

View File

@ -294,6 +294,11 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
// attachment, hence this min:
fMaxRenderTargetSize = SkTMin(fMaxTextureSize, fMaxRenderTargetSize);
// This GPU seems to have problems when tiling small textures
if (kPowerVR54x_GrGLRenderer == ctxInfo.renderer()) {
fMinTextureSize = 16;
}
fGpuTracingSupport = ctxInfo.hasExtension("GL_EXT_debug_marker");
// Disable scratch texture reuse on Mali and Adreno devices