Attempt to simplify NPOT texture caps. Also fixes case where textures would unnecessarily be bloated to POT. Adds setting of sampler's filter setting in paint conversion.

git-svn-id: http://skia.googlecode.com/svn/trunk@751 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bsalomon@google.com 2011-02-01 22:56:16 +00:00
parent f7c157610f
commit 0748f217ba
5 changed files with 97 additions and 121 deletions

View File

@ -54,28 +54,6 @@ public:
*/
static GrGpu* Create(Engine, Platform3DContext context3D);
/**
* Describes levels of support for non-power-of-two textures.
*/
enum NPOTTextureTypes {
/**
* no support for NPOT textures
*/
kNone_NPOTTextureType,
/**
* only clamp is supported for textures
*/
kNoRepeat_NPOTTextureType,
/**
* no texture restrictions at all, but rendertargets must be POW2
*/
kNonRendertarget_NPOTTextureType,
/**
* no POW2 restrictions at all
*/
kFull_NPOTTextureType
};
/**
* Used to control the level of antialiasing available for a rendertarget.
* Anti-alias quality levels depend on the underlying API/GPU capabilities.
@ -173,7 +151,10 @@ public:
void unimpl(const char[]);
/**
* Creates a texture object
* Creates a texture object. If desc width or height is not a power of
* two but underlying API requires a power of two texture then srcData
* will be embedded in a power of two texture. The extra width and height
* is filled as though srcData were rendered clamped into the texture.
*
* @param desc describes the texture to be created.
* @param srcData texel data to load texture. Begins with full-size
@ -278,14 +259,25 @@ public:
int minRenderTargetHeight() const { return fMinRenderTargetHeight; }
/**
* Retrieves the level of NPOT texture support. Regardless of support level
* NPOT textures can always be created, but internally they may be imbedded
* in a POT texture. An exception is paletted textures which must be
* specified as a POT when npotTextureSupport() is not Full.
* Returns true if NPOT textures can be created
*
* @return the level of NPOT texture support.
* @return true if NPOT textures can be created
*/
NPOTTextureTypes npotTextureSupport() const { return fNPOTTextureSupport; }
bool npotTextureSupport() const { return fNPOTTextureSupport; }
/**
* Returns true if NPOT textures can be repeat/mirror tiled.
*
* @return true if NPOT textures can be tiled
*/
bool npotTextureTileSupport() const { return fNPOTTextureTileSupport; }
/**
* Returns true if a NPOT texture can be a rendertarget
*
* @return the true if NPOT texture/rendertarget can be created.
*/
bool npotRenderTargetSupport() const { return fNPOTRenderTargetSupport; }
int maxTextureDimension() const { return fMaxTextureDimension; }
@ -374,8 +366,10 @@ protected:
// defaults to false, subclass can set true to support palleted textures
bool f8bitPaletteSupport;
// defaults to false, subclass can set higher support level
NPOTTextureTypes fNPOTTextureSupport;
// set by subclass
bool fNPOTTextureSupport;
bool fNPOTTextureTileSupport;
bool fNPOTRenderTargetSupport;
// True if only one stencil pass is required to implement the winding path
// fill rule. Subclass responsible for setting this value.

View File

@ -260,22 +260,21 @@ bool GrContext::supportsIndex8PixelConfig(const GrSamplerState& sampler,
return false;
}
bool needsRepeat = sampler.getWrapX() != GrSamplerState::kClamp_WrapMode ||
sampler.getWrapY() != GrSamplerState::kClamp_WrapMode;
bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
switch (fGpu->npotTextureSupport()) {
case GrGpu::kNone_NPOTTextureType:
return isPow2;
case GrGpu::kNoRepeat_NPOTTextureType:
return isPow2 || !needsRepeat;
case GrGpu::kNonRendertarget_NPOTTextureType:
case GrGpu::kFull_NPOTTextureType:
return true;
if (!isPow2) {
if (!fGpu->npotTextureSupport()) {
return false;
}
bool tiled = sampler.getWrapX() != GrSamplerState::kClamp_WrapMode ||
sampler.getWrapY() != GrSamplerState::kClamp_WrapMode;
if (tiled && !fGpu->npotTextureTileSupport()) {
return false;
}
}
// should never get here
GrAssert(!"Bad enum from fGpu->npotTextureSupport");
return false;
return true;
}
////////////////////////////////////////////////////////////////////////////////
@ -1141,10 +1140,15 @@ bool GrContext::finalizeTextureKey(GrTextureKey* key,
uint32_t bits = 0;
uint16_t width = key->width();
uint16_t height = key->height();
if (fGpu->npotTextureSupport() < GrGpu::kNonRendertarget_NPOTTextureType) {
if ((sampler.getWrapX() != GrSamplerState::kClamp_WrapMode ||
sampler.getWrapY() != GrSamplerState::kClamp_WrapMode) &&
(!GrIsPow2(width) || !GrIsPow2(height))) {
if (!fGpu->npotTextureTileSupport()) {
bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
bool tiled = (sampler.getWrapX() != GrSamplerState::kClamp_WrapMode) ||
(sampler.getWrapY() != GrSamplerState::kClamp_WrapMode);
if (tiled && !isPow2) {
bits |= 1;
bits |= sampler.isFilter() ? 2 : 0;
}

View File

@ -57,7 +57,6 @@ bool GrTexture::PixelConfigIsOpaque(PixelConfig config) {
extern void gr_run_unittests();
GrGpu::GrGpu() : f8bitPaletteSupport(false),
fNPOTTextureSupport(kNone_NPOTTextureType),
fQuadIndexBuffer(NULL),
fUnitSquareVertexBuffer(NULL) {
#if GR_DEBUG

View File

@ -250,18 +250,20 @@ GrGpuGL::GrGpuGL() {
}
#if GR_SUPPORT_GLDESKTOP
fNPOTTextureSupport =
(major >= 2 || has_gl_extension("GL_ARB_texture_non_power_of_two")) ?
kFull_NPOTTextureType :
kNone_NPOTTextureType;
#else
if (has_gl_extension("GL_OES_texture_npot")) {
fNPOTTextureSupport = kFull_NPOTTextureType;
} else if (major >= 2 ||
has_gl_extension("GL_APPLE_texture_2D_limited_npot")) {
fNPOTTextureSupport = kNoRepeat_NPOTTextureType;
if (major >= 2 || has_gl_extension("GL_ARB_texture_non_power_of_two")) {
fNPOTTextureTileSupport = true;
fNPOTTextureSupport = true;
} else {
fNPOTTextureSupport = kNone_NPOTTextureType;
fNPOTTextureTileSupport = false;
fNPOTTextureSupport = false;
}
#else
if (major >= 2) {
fNPOTTextureSupport = true;
fNPOTTextureTileSupport = has_gl_extension("GL_OES_texture_npot");
} else {
fNPOTTextureSupport = has_gl_extension("GL_APPLE_texture_2D_limited_npot");
fNPOTTextureTileSupport = false;
}
#endif
////////////////////////////////////////////////////////////////////////////
@ -269,16 +271,16 @@ GrGpuGL::GrGpuGL() {
// these a preprocess that generate some compile time constants.
// sanity check to make sure we can at least create an FBO from a POT texture
if (fNPOTTextureSupport < kFull_NPOTTextureType) {
bool npotFBOSuccess = fbo_test(fExts, 128, 128);
if (gPrintStartupSpew) {
if (!npotFBOSuccess) {
GrPrintf("FBO Sanity Test: FAILED\n");
} else {
GrPrintf("FBO Sanity Test: PASSED\n");
}
bool simpleFBOSuccess = fbo_test(fExts, 128, 128);
if (gPrintStartupSpew) {
if (!simpleFBOSuccess) {
GrPrintf("FBO Sanity Test: FAILED\n");
} else {
GrPrintf("FBO Sanity Test: PASSED\n");
}
}
GrAssert(simpleFBOSuccess);
/* Experimentation has found that some GLs that support NPOT textures
do not support FBOs with a NPOT texture. They report "unsupported" FBO
@ -287,34 +289,26 @@ GrGpuGL::GrGpuGL() {
texture. Presumably, the implementation bloats the renderbuffer
internally to the next POT.
*/
if (fNPOTTextureSupport == kFull_NPOTTextureType) {
bool npotFBOSuccess = fbo_test(fExts, 200, 200);
if (!npotFBOSuccess) {
fNPOTTextureSupport = kNonRendertarget_NPOTTextureType;
if (gPrintStartupSpew) {
GrPrintf("NPOT Renderbuffer Test: FAILED\n");
bool fNPOTRenderTargetSupport = false;
if (fNPOTTextureSupport) {
fNPOTRenderTargetSupport = fbo_test(fExts, 200, 200);
}
if (gPrintStartupSpew) {
if (fNPOTTextureSupport) {
GrPrintf("NPOT textures supported\n");
if (fNPOTTextureTileSupport) {
GrPrintf("NPOT texture tiling supported\n");
} else {
GrPrintf("NPOT texture tiling NOT supported\n");
}
if (fNPOTRenderTargetSupport) {
GrPrintf("NPOT render targets supported\n");
} else {
GrPrintf("NPOT render targets NOT supported\n");
}
} else {
if (gPrintStartupSpew) {
GrPrintf("NPOT Renderbuffer Test: PASSED\n");
}
}
}
if (gPrintStartupSpew) {
switch (fNPOTTextureSupport) {
case kNone_NPOTTextureType:
GrPrintf("NPOT Support: NONE\n");
break;
case kNoRepeat_NPOTTextureType:
GrPrintf("NPOT Support: NO REPEAT\n");
break;
case kNonRendertarget_NPOTTextureType:
GrPrintf("NPOT Support: NO FBOTEX\n");
break;
case kFull_NPOTTextureType:
GrPrintf("NPOT Support: FULL\n");
break;
GrPrintf("NPOT textures NOT supported\n");
}
}
@ -329,8 +323,8 @@ GrGpuGL::GrGpuGL() {
if (gPrintStartupSpew) {
GrPrintf("Small height FBO texture experiments\n");
}
for (GLuint i = 1; i <= 256;
(kFull_NPOTTextureType != fNPOTTextureSupport) ? i *= 2 : ++i) {
for (GLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? ++i : i *= 2) {
GLuint w = maxRenderSize;
GLuint h = i;
if (fbo_test(fExts, w, h)) {
@ -351,8 +345,7 @@ GrGpuGL::GrGpuGL() {
GrPrintf("Small width FBO texture experiments\n");
}
fMinRenderTargetWidth = GR_MAX_GLUINT;
for (GLuint i = 1; i <= 256;
(kFull_NPOTTextureType != fNPOTTextureSupport) ? i *= 2 : ++i) {
for (GLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? i *= 2 : ++i) {
GLuint w = i;
GLuint h = maxRenderSize;
if (fbo_test(fExts, w, h)) {
@ -369,22 +362,7 @@ GrGpuGL::GrGpuGL() {
}
GrAssert(GR_INVAL_GLINT != fMinRenderTargetWidth);
#if GR_IOS_BUILD
/*
The iPad seems to fail, at least sometimes, if the height is < 16,
so we pin the values here for now. A better fix might be to
conditionalize this based on known that its an iPad (or some other
check).
*/
fMinRenderTargetWidth = GrMax<GLuint>(fMinRenderTargetWidth, 16);
fMinRenderTargetHeight = GrMax<GLuint>(fMinRenderTargetHeight, 16);
#endif
GR_GL_GetIntegerv(GL_MAX_TEXTURE_SIZE, &fMaxTextureDimension);
#if GR_COLLECT_STATS
++fStats.fRenderTargetChngCnt;
#endif
}
GrGpuGL::~GrGpuGL() {
@ -607,18 +585,19 @@ GrTexture* GrGpuGL::createTexture(const TextureDesc& desc,
}
#endif
if (fNPOTTextureSupport < kNonRendertarget_NPOTTextureType ||
(fNPOTTextureSupport == kNonRendertarget_NPOTTextureType &&
renderTarget)) {
glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
}
if (renderTarget) {
if (!this->npotRenderTargetSupport()) {
glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
}
glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
glDesc.fAllocWidth);
glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
glDesc.fAllocHeight);
} else if (!this->npotTextureSupport()) {
glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
}
GR_GL(BindTexture(GL_TEXTURE_2D, glDesc.fTextureID));

View File

@ -405,7 +405,7 @@ bool SkGpuDevice::skPaint2GrPaintShader(const SkPaint& skPaint,
return false;
}
grPaint->fSampler.setSampleMode(sampleMode);
grPaint->fSampler.setFilter(skPaint.isFilterBitmap());
grPaint->fSampler.setWrapX(sk_tile_mode_to_grwrap(tileModes[0]));
grPaint->fSampler.setWrapY(sk_tile_mode_to_grwrap(tileModes[1]));