Reduce gets of ext string and check validity of stencil format enums

Review URL: http://codereview.appspot.com/4678043/



git-svn-id: http://skia.googlecode.com/svn/trunk@1801 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bsalomon@google.com 2011-07-06 17:47:02 +00:00
Родитель 25fd36c7ef
Коммит 2c17fcdc45
5 изменённых файлов: 138 добавлений и 68 удалений

Просмотреть файл

@ -31,14 +31,17 @@
* Helpers for glGetString()
*/
// these variants assume caller already has a string from glGetString()
void gl_version_from_string(int* major, int* minor,
const char* versionString);
float gl_version_as_float_from_string(const char* versionString);
bool has_gl_extension_from_string(const char* ext,
const char* extensionString);
// these variants call glGetString()
bool has_gl_extension(const char* ext);
void gl_version(int* major, int* minor);
float gl_version_as_float();
////////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -54,6 +54,25 @@ void gl_version_from_string(int* major, int* minor,
}
}
float gl_version_as_float_from_string(const char* versionString) {
int major, minor;
gl_version_from_string(&major, &minor, versionString);
GrAssert(minor >= 0);
// AFAIK there are only single digit minor numbers
if (minor < 10) {
return major + minor / 10.f;
} else if (minor < 100) {
return major + minor / 100.f;
} else if (minor < 1000) {
return major + minor / 1000.f;
} else {
GrAssert(!"Why so many digits in minor revision number?");
char temp[32];
sprintf(temp, "%d.%d", major, minor);
return (float) atof(temp);
}
}
bool has_gl_extension_from_string(const char* ext,
const char* extensionString) {
int extLength = strlen(ext);
@ -72,7 +91,6 @@ bool has_gl_extension_from_string(const char* ext,
return false;
}
GR_API void GrGLSetGLInterface(GrGLInterface* gl_interface) {
gGLInterface = gl_interface;
}
@ -94,6 +112,12 @@ void gl_version(int* major, int* minor) {
gl_version_from_string(major, minor, v);
}
float gl_version_as_float() {
const char* v = reinterpret_cast<const char*>(
GrGLGetGLInterface()->fGetString(GR_GL_VERSION));
return gl_version_as_float_from_string(v);
}
bool GrGLInterface::validateShaderFunctions() const {
// required for GrGpuGLShaders
if (NULL == fAttachShader ||

Просмотреть файл

@ -262,7 +262,10 @@ static int probe_for_min_render_target_width(bool hasNPOTRenderTargetSupport,
}
GrGpuGL::GrGpuGL() {
GrGpuGL::GrGpuGL()
: fStencilFormats(8) {
GrGLClearErr();
if (gPrintStartupSpew) {
GrPrintf("------------------------- create GrGpuGL %p --------------\n",
@ -277,9 +280,10 @@ GrGpuGL::GrGpuGL() {
GrGLGetGLInterface()->fGetString(GR_GL_EXTENSIONS));
}
GrGLClearErr();
fGLVersion = gl_version_as_float();
fExtensionString = (const char*) GR_GL(GetString(GR_GL_EXTENSIONS));
resetDirtyFlags();
this->resetDirtyFlags();
GrGLint maxTextureUnits;
// check FS and fixed-function texture unit limits
@ -307,8 +311,7 @@ GrGpuGL::GrGpuGL() {
////////////////////////////////////////////////////////////////////////////
// Check for supported features.
int major, minor;
gl_version(&major, &minor);
this->setupStencilFormats();
GrGLint numFormats;
GR_GL_GetIntegerv(GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
@ -333,19 +336,19 @@ GrGpuGL::GrGpuGL() {
memset(fAASamples, 0, sizeof(fAASamples));
fMSFBOType = kNone_MSFBO;
if (GR_GL_SUPPORT_ES) {
if (has_gl_extension("GL_CHROMIUM_framebuffer_multisample")) {
if (this->hasExtension("GL_CHROMIUM_framebuffer_multisample")) {
// chrome's extension is equivalent to the EXT msaa
// and fbo_blit extensions.
fMSFBOType = kDesktopEXT_MSFBO;
} else if (has_gl_extension("GL_APPLE_framebuffer_multisample")) {
} else if (this->hasExtension("GL_APPLE_framebuffer_multisample")) {
fMSFBOType = kAppleES_MSFBO;
}
} else {
GrAssert(GR_GL_SUPPORT_DESKTOP);
if ((major >= 3) || has_gl_extension("GL_ARB_framebuffer_object")) {
if ((fGLVersion >= 3.f) || this->hasExtension("GL_ARB_framebuffer_object")) {
fMSFBOType = kDesktopARB_MSFBO;
} else if (has_gl_extension("GL_EXT_framebuffer_multisample") &&
has_gl_extension("GL_EXT_framebuffer_blit")) {
} else if (this->hasExtension("GL_EXT_framebuffer_multisample") &&
this->hasExtension("GL_EXT_framebuffer_blit")) {
fMSFBOType = kDesktopEXT_MSFBO;
}
}
@ -386,10 +389,10 @@ GrGpuGL::GrGpuGL() {
fFSAASupport = fAASamples[kHigh_GrAALevel] > 0;
if (GR_GL_SUPPORT_DESKTOP) {
fHasStencilWrap = (major >= 2 || (major == 1 && minor >= 4)) ||
has_gl_extension("GL_EXT_stencil_wrap");
fHasStencilWrap = (fGLVersion >= 1.4f) ||
this->hasExtension("GL_EXT_stencil_wrap");
} else {
fHasStencilWrap = (major >= 2) || has_gl_extension("GL_OES_stencil_wrap");
fHasStencilWrap = (fGLVersion >= 2.0f) || this->hasExtension("GL_OES_stencil_wrap");
}
if (gPrintStartupSpew) {
GrPrintf("Stencil Wrap: %s\n", (fHasStencilWrap ? "YES" : "NO"));
@ -399,18 +402,17 @@ GrGpuGL::GrGpuGL() {
// we could also look for GL_ATI_separate_stencil extension or
// GL_EXT_stencil_two_side but they use different function signatures
// than GL2.0+ (and than each other).
fTwoSidedStencilSupport = (major >= 2);
fTwoSidedStencilSupport = (fGLVersion >= 2.f);
// supported on GL 1.4 and higher or by extension
fStencilWrapOpsSupport = (major > 1) ||
((1 == major) && (minor >= 4)) ||
has_gl_extension("GL_EXT_stencil_wrap");
fStencilWrapOpsSupport = (fGLVersion >= 1.4f) ||
this->hasExtension("GL_EXT_stencil_wrap");
} else {
// ES 2 has two sided stencil but 1.1 doesn't. There doesn't seem to be
// an ES1 extension.
fTwoSidedStencilSupport = (major >= 2);
fTwoSidedStencilSupport = (fGLVersion >= 2.f);
// stencil wrap support is in ES2, ES1 requires extension.
fStencilWrapOpsSupport = (major > 1) ||
has_gl_extension("GL_OES_stencil_wrap");
fStencilWrapOpsSupport = (fGLVersion >= 2.f) ||
this->hasExtension("GL_OES_stencil_wrap");
}
if (gPrintStartupSpew) {
GrPrintf("Stencil Caps: TwoSide: %s, Wrap: %s\n",
@ -421,7 +423,7 @@ GrGpuGL::GrGpuGL() {
if (GR_GL_SUPPORT_DESKTOP) {
fRGBA8Renderbuffer = true;
} else {
fRGBA8Renderbuffer = has_gl_extension("GL_OES_rgb8_rgba8");
fRGBA8Renderbuffer = this->hasExtension("GL_OES_rgb8_rgba8");
}
if (gPrintStartupSpew) {
GrPrintf("RGBA Renderbuffer: %s\n", (fRGBA8Renderbuffer ? "YES" : "NO"));
@ -430,7 +432,7 @@ GrGpuGL::GrGpuGL() {
if (GR_GL_SUPPORT_ES) {
if (GR_GL_32BPP_COLOR_FORMAT == GR_GL_BGRA) {
GrAssert(has_gl_extension("GL_EXT_texture_format_BGRA8888"));
GrAssert(this->hasExtension("GL_EXT_texture_format_BGRA8888"));
}
}
@ -438,7 +440,7 @@ GrGpuGL::GrGpuGL() {
fBufferLockSupport = true; // we require VBO support and the desktop VBO
// extension includes glMapBuffer.
} else {
fBufferLockSupport = has_gl_extension("GL_OES_mapbuffer");
fBufferLockSupport = this->hasExtension("GL_OES_mapbuffer");
}
if (gPrintStartupSpew) {
@ -446,7 +448,8 @@ GrGpuGL::GrGpuGL() {
}
if (GR_GL_SUPPORT_DESKTOP) {
if (major >= 2 || has_gl_extension("GL_ARB_texture_non_power_of_two")) {
if (fGLVersion >= 2.f ||
this->hasExtension("GL_ARB_texture_non_power_of_two")) {
fNPOTTextureTileSupport = true;
fNPOTTextureSupport = true;
} else {
@ -454,12 +457,12 @@ GrGpuGL::GrGpuGL() {
fNPOTTextureSupport = false;
}
} else {
if (major >= 2) {
if (fGLVersion >= 2.f) {
fNPOTTextureSupport = true;
fNPOTTextureTileSupport = has_gl_extension("GL_OES_texture_npot");
fNPOTTextureTileSupport = this->hasExtension("GL_OES_texture_npot");
} else {
fNPOTTextureSupport =
has_gl_extension("GL_APPLE_texture_2D_limited_npot");
this->hasExtension("GL_APPLE_texture_2D_limited_npot");
fNPOTTextureTileSupport = false;
}
}
@ -685,37 +688,57 @@ GrRenderTarget* GrGpuGL::onCreateRenderTargetFrom3DApiState() {
///////////////////////////////////////////////////////////////////////////////
static const GrGLuint UNKNOWN_BITS = ~0;
void GrGpuGL::setupStencilFormats() {
struct StencilFormat {
GrGLenum fEnum;
GrGLuint fBits;
bool fPacked;
};
// Build up list of legal stencil formats (though perhaps not supported on
// the particular gpu/driver) from most preferred to least.
const StencilFormat* GrGLStencilFormats(int* count) {
// defines stencil formats from more to less preferred
static const StencilFormat desktopStencilFormats[] = {
{GR_GL_STENCIL_INDEX8, 8, false},
{GR_GL_STENCIL_INDEX16, 16, false},
{GR_GL_DEPTH24_STENCIL8, 8, true },
{GR_GL_STENCIL_INDEX4, 4, false},
{GR_GL_STENCIL_INDEX, UNKNOWN_BITS, false},
{GR_GL_DEPTH_STENCIL, UNKNOWN_BITS, true },
};
static const StencilFormat esStencilFormats[] = {
{GR_GL_STENCIL_INDEX8, 8, false},
{GR_GL_DEPTH24_STENCIL8, 8, true },
{GR_GL_STENCIL_INDEX4, 4, false},
};
// these consts are in order of most preferred to least preferred
// we don't bother with GL_STENCIL_INDEX1 or GL_DEPTH32F_STENCIL8
static const StencilFormat gS8 = {GR_GL_STENCIL_INDEX8, 8, false};
static const StencilFormat gS16 = {GR_GL_STENCIL_INDEX16, 16, false};
static const StencilFormat gD24S8 = {GR_GL_DEPTH24_STENCIL8, 8, true };
static const StencilFormat gS4 = {GR_GL_STENCIL_INDEX4, 4, false};
static const StencilFormat gS = {GR_GL_STENCIL_INDEX, gUNKNOWN_BITCOUNT, false};
static const StencilFormat gDS = {GR_GL_DEPTH_STENCIL, gUNKNOWN_BITCOUNT, true };
if (GR_GL_SUPPORT_DESKTOP) {
*count = GR_ARRAY_COUNT(desktopStencilFormats);
return desktopStencilFormats;
bool supportsPackedDS = fGLVersion >= 3.0f ||
this->hasExtension("GL_EXT_packed_depth_stencil") ||
this->hasExtension("GL_ARB_framebuffer_object");
// S1 thru S16 formats are in GL 3.0+, EXT_FBO, and ARB_FBO since we
// require FBO support we can expect these are legal formats and don't
// check. These also all support the unsized GL_STENCIL_INDEX.
fStencilFormats.push_back() = gS8;
fStencilFormats.push_back() = gS16;
if (supportsPackedDS) {
fStencilFormats.push_back() = gD24S8;
}
fStencilFormats.push_back() = gS4;
if (supportsPackedDS) {
fStencilFormats.push_back() = gDS;
}
} else {
*count = GR_ARRAY_COUNT(esStencilFormats);
return esStencilFormats;
// ES2 has STENCIL_INDEX8 without extensions.
// ES1 with GL_OES_framebuffer_object (which we require for ES1)
// introduces tokens for S1 thu S8 but there are separate extensions
// that make them legal (GL_OES_stencil1, ...).
// GL_OES_packed_depth_stencil adds DEPTH24_STENCIL8
// ES doesn't support using the unsized formats.
if (fGLVersion >= 2.f || this->hasExtension("GL_OES_stencil8")) {
fStencilFormats.push_back() = gS8;
}
//fStencilFormats.push_back() = gS16;
if (this->hasExtension("GL_OES_packed_depth_stencil")) {
fStencilFormats.push_back() = gD24S8;
}
if (this->hasExtension("GL_OES_stencil4")) {
fStencilFormats.push_back() = gS4;
}
// we require some stencil format.
GrAssert(fStencilFormats.count() > 0);
}
}
@ -983,9 +1006,8 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
err = ~GR_GL_NO_ERROR;
int stencilFmtCnt;
const StencilFormat* stencilFormats = NULL;
if (rtIDs.fStencilRenderbufferID) {
stencilFormats = GrGLStencilFormats(&stencilFmtCnt);
stencilFmtCnt = fStencilFormats.count();
} else {
stencilFmtCnt = 1; // only 1 attempt when we don't need a stencil
}
@ -1003,12 +1025,12 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
GR_GL_NO_ERR(RenderbufferStorageMultisample(
GR_GL_RENDERBUFFER,
samples,
stencilFormats[sIdx].fEnum,
fStencilFormats[sIdx].fEnum,
glDesc.fAllocWidth,
glDesc.fAllocHeight));
} else {
GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
stencilFormats[sIdx].fEnum,
fStencilFormats[sIdx].fEnum,
glDesc.fAllocWidth,
glDesc.fAllocHeight));
}
@ -1064,7 +1086,7 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
rtIDs.fStencilRenderbufferID));
// if it is a packed format bind to depth also, otherwise
// we may get an unsupported fbo completeness result
if (stencilFormats[sIdx].fPacked) {
if (fStencilFormats[sIdx].fPacked) {
GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
GR_GL_DEPTH_ATTACHMENT,
GR_GL_RENDERBUFFER,
@ -1076,7 +1098,7 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
// undo the depth bind
if (rtIDs.fStencilRenderbufferID &&
stencilFormats[sIdx].fPacked) {
fStencilFormats[sIdx].fPacked) {
GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
GR_GL_DEPTH_ATTACHMENT,
GR_GL_RENDERBUFFER,
@ -1088,10 +1110,10 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
failed = false;
if (rtIDs.fStencilRenderbufferID) {
fLastSuccessfulStencilFmtIdx = sIdx;
if (UNKNOWN_BITS == stencilFormats[sIdx].fBits) {
if (gUNKNOWN_BITCOUNT == fStencilFormats[sIdx].fBits) {
GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
} else {
glDesc.fStencilBits = stencilFormats[sIdx].fBits;
glDesc.fStencilBits = fStencilFormats[sIdx].fBits;
}
}
break;

Просмотреть файл

@ -25,6 +25,8 @@
#include "GrGLVertexBuffer.h"
#include "GrGLIndexBuffer.h"
#include "SkString.h"
class GrGpuGL : public GrGpu {
public:
virtual ~GrGpuGL();
@ -48,6 +50,10 @@ protected:
DrState fHWDrawState;
bool fHWStencilClip;
// read these once at begining and then never again
SkString fExtensionString;
float fGLVersion;
// As flush of GL state proceeds it updates fHDrawState
// to reflect the new state. Later parts of the state flush
// may perform cascaded changes but cannot refer to fHWDrawState.
@ -127,6 +133,10 @@ protected:
GrBlendCoeff srcCoeff,
GrBlendCoeff dstCoeff);
bool hasExtension(const char* ext) {
return has_gl_extension_from_string(ext, fExtensionString.c_str());
}
// adjusts texture matrix to account for orientation, size, and npotness
static void AdjustTextureMatrix(const GrGLTexture* texture,
GrSamplerState::SampleMode mode,
@ -142,6 +152,9 @@ protected:
private:
// determines valid stencil formats
void setupStencilFormats();
// notify callbacks to update state tracking when related
// objects are bound to GL or deleted outside of the class
void notifyVertexBufferBind(const GrGLVertexBuffer* buffer);
@ -175,6 +188,16 @@ private:
friend class GrGLTexture;
friend class GrGLRenderTarget;
static const GrGLuint gUNKNOWN_BITCOUNT = ~0;
struct StencilFormat {
GrGLenum fEnum;
GrGLuint fBits;
bool fPacked;
};
GrTArray<StencilFormat, true> fStencilFormats;
bool fHWBlendDisabled;
GrGLuint fAASamples[4];

Просмотреть файл

@ -248,14 +248,12 @@ void GrGpuGLShaders::ProgramUnitTest() {
GrGpuGLShaders::GrGpuGLShaders() {
resetContext();
int major, minor;
gl_version(&major, &minor);
f4X4DownsampleFilterSupport = true;
if (GR_GL_SUPPORT_DESKTOP) {
fDualSourceBlendingSupport =
major > 3 ||(3 == major && 3 <= minor) ||
has_gl_extension("GL_ARB_blend_func_extended");
fGLVersion >= 3.3f ||
this->hasExtension("GL_ARB_blend_func_extended");
} else {
fDualSourceBlendingSupport = false;
}