Bug 686732 - Implement minimal-capabilities WebGL mode - r=bjacob

This commit is contained in:
Christoph Diehl 2011-10-13 08:09:22 -04:00
Родитель 9a37a3f8e9
Коммит e2538cc5de
5 изменённых файлов: 163 добавлений и 46 удалений

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

@ -965,6 +965,10 @@ NS_IMETHODIMP
WebGLContext::GetExtension(const nsAString& aName, nsIWebGLExtension **retval)
{
*retval = nsnull;
if (mDisableExtensions) {
return NS_OK;
}
// handle simple extensions that don't need custom objects first
WebGLExtensionID ei = WebGLExtensionID_Max;
@ -1301,6 +1305,12 @@ WebGLActiveInfo::GetName(nsAString & aName)
NS_IMETHODIMP
WebGLContext::GetSupportedExtensions(nsIVariant **retval)
{
*retval = nsnull;
if (mDisableExtensions) {
return NS_OK;
}
nsCOMPtr<nsIWritableVariant> wrval = do_CreateInstance("@mozilla.org/variant;1");
NS_ENSURE_TRUE(wrval, NS_ERROR_FAILURE);

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

@ -63,6 +63,24 @@
#include "CheckedInt.h"
/*
* Minimum value constants defined in 6.2 State Tables of OpenGL ES - 2.0.25
* https://bugzilla.mozilla.org/show_bug.cgi?id=686732
*
* Exceptions: some of the following values are set to higher values than in the spec because
* the values in the spec are ridiculously low. They are explicitly marked below
*/
#define MINVALUE_GL_MAX_TEXTURE_SIZE 1024 // Different from the spec, which sets it to 64 on page 162
#define MINVALUE_GL_MAX_CUBE_MAP_TEXTURE_SIZE 512 // Different from the spec, which sets it to 16 on page 162
#define MINVALUE_GL_MAX_VERTEX_ATTRIBS 8 // Page 164
#define MINVALUE_GL_MAX_FRAGMENT_UNIFORM_VECTORS 16 // Page 164
#define MINVALUE_GL_MAX_VERTEX_UNIFORM_VECTORS 128 // Page 164
#define MINVALUE_GL_MAX_VARYING_VECTORS 8 // Page 164
#define MINVALUE_GL_MAX_TEXTURE_IMAGE_UNITS 8 // Page 164
#define MINVALUE_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0 // Page 164
#define MINVALUE_GL_MAX_RENDERBUFFER_SIZE 1024 // Different from the spec, which sets it to 1 on page 164
#define MINVALUE_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 8 // Page 164
class nsIDocShell;
class nsIPropertyBag;
@ -415,6 +433,10 @@ public:
GLenum currentGLError;
UpdateWebGLErrorAndClearGLError(&currentGLError);
}
bool MinCapabilityMode() const {
return mMinCapability;
}
protected:
void SetDontKnowIfNeedFakeBlack() {
@ -456,6 +478,8 @@ protected:
bool mResetLayer;
bool mVerbose;
bool mOptionsFrozen;
bool mMinCapability;
bool mDisableExtensions;
WebGLuint mActiveTexture;
WebGLenum mWebGLError;

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

@ -1900,7 +1900,61 @@ WebGLContext::GetParameter(PRUint32 pname, nsIVariant **retval)
NS_ENSURE_TRUE(wrval, NS_ERROR_FAILURE);
MakeContextCurrent();
if (MinCapabilityMode()) {
bool override = true;
switch(pname) {
//
// Single-value params
//
// int
case LOCAL_GL_MAX_VERTEX_ATTRIBS:
wrval->SetAsInt32(MINVALUE_GL_MAX_VERTEX_ATTRIBS);
break;
case LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS:
wrval->SetAsInt32(MINVALUE_GL_MAX_FRAGMENT_UNIFORM_VECTORS);
break;
case LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS:
wrval->SetAsInt32(MINVALUE_GL_MAX_VERTEX_UNIFORM_VECTORS);
break;
case LOCAL_GL_MAX_VARYING_VECTORS:
wrval->SetAsInt32(MINVALUE_GL_MAX_VARYING_VECTORS);
break;
case LOCAL_GL_MAX_TEXTURE_SIZE:
wrval->SetAsInt32(MINVALUE_GL_MAX_TEXTURE_SIZE);
break;
case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE:
wrval->SetAsInt32(MINVALUE_GL_MAX_CUBE_MAP_TEXTURE_SIZE);
break;
case LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS:
wrval->SetAsInt32(MINVALUE_GL_MAX_TEXTURE_IMAGE_UNITS);
break;
case LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
wrval->SetAsInt32(MINVALUE_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
break;
case LOCAL_GL_MAX_RENDERBUFFER_SIZE:
wrval->SetAsInt32(MINVALUE_GL_MAX_RENDERBUFFER_SIZE);
break;
default:
override = false;
}
if (override) {
*retval = wrval.forget().get();
return NS_OK;
}
}
switch (pname) {
//
// String params

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

@ -63,7 +63,11 @@ WebGLProgram::UpdateInfo(gl::GLContext *gl)
gl->fGetProgramiv(mName, LOCAL_GL_ACTIVE_ATTRIBUTES, &mAttribCount);
GLint numVertexAttribs;
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, &numVertexAttribs);
if (mContext->MinCapabilityMode()) {
numVertexAttribs = MINVALUE_GL_MAX_VERTEX_ATTRIBS;
} else {
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, &numVertexAttribs);
}
mAttribsInUse.clear();
mAttribsInUse.resize(numVertexAttribs);
@ -503,6 +507,9 @@ WebGLContext::InitAndValidateGL()
return PR_FALSE;
}
mMinCapability = Preferences::GetBool("webgl.min_capability_mode", false);
mDisableExtensions = Preferences::GetBool("webgl.disable-extensions", false);
mActiveTexture = 0;
mWebGLError = LOCAL_GL_NO_ERROR;
@ -533,10 +540,14 @@ WebGLContext::InitAndValidateGL()
gl->fEnableVertexAttribArray(0);
}
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, &mGLMaxVertexAttribs);
if (MinCapabilityMode()) {
mGLMaxVertexAttribs = MINVALUE_GL_MAX_VERTEX_ATTRIBS;
} else {
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, &mGLMaxVertexAttribs);
}
if (mGLMaxVertexAttribs < 8) {
LogMessage("GL_MAX_VERTEX_ATTRIBS: %d is < 8!", mGLMaxVertexAttribs);
return PR_FALSE;
return false;
}
mAttribBuffers.SetLength(mGLMaxVertexAttribs);
@ -544,17 +555,30 @@ WebGLContext::InitAndValidateGL()
// Note: GL_MAX_TEXTURE_UNITS is fixed at 4 for most desktop hardware,
// even though the hardware supports much more. The
// GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS value is the accurate value.
gl->fGetIntegerv(LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mGLMaxTextureUnits);
if (MinCapabilityMode()) {
mGLMaxTextureUnits = MINVALUE_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS;
} else {
gl->fGetIntegerv(LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mGLMaxTextureUnits);
}
if (mGLMaxTextureUnits < 8) {
LogMessage("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: %d is < 8!", mGLMaxTextureUnits);
return PR_FALSE;
return false;
}
mBound2DTextures.SetLength(mGLMaxTextureUnits);
mBoundCubeMapTextures.SetLength(mGLMaxTextureUnits);
gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &mGLMaxTextureSize);
gl->fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mGLMaxCubeMapTextureSize);
if (MinCapabilityMode()) {
mGLMaxTextureSize = MINVALUE_GL_MAX_TEXTURE_SIZE;
mGLMaxCubeMapTextureSize = MINVALUE_GL_MAX_CUBE_MAP_TEXTURE_SIZE;
mGLMaxTextureImageUnits = MINVALUE_GL_MAX_TEXTURE_IMAGE_UNITS;
mGLMaxVertexTextureImageUnits = MINVALUE_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS;
} else {
gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &mGLMaxTextureSize);
gl->fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mGLMaxCubeMapTextureSize);
gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS, &mGLMaxTextureImageUnits);
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mGLMaxVertexTextureImageUnits);
}
#ifdef XP_MACOSX
if (gl->Vendor() == gl::GLContext::VendorIntel) {
@ -564,48 +588,51 @@ WebGLContext::InitAndValidateGL()
}
#endif
gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS, &mGLMaxTextureImageUnits);
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mGLMaxVertexTextureImageUnits);
if (gl->HasES2Compatibility()) {
gl->fGetIntegerv(LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS, &mGLMaxFragmentUniformVectors);
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS, &mGLMaxVertexUniformVectors);
gl->fGetIntegerv(LOCAL_GL_MAX_VARYING_VECTORS, &mGLMaxVaryingVectors);
if (MinCapabilityMode()) {
mGLMaxFragmentUniformVectors = MINVALUE_GL_MAX_FRAGMENT_UNIFORM_VECTORS;
mGLMaxVertexUniformVectors = MINVALUE_GL_MAX_VERTEX_UNIFORM_VECTORS;
mGLMaxVaryingVectors = MINVALUE_GL_MAX_VARYING_VECTORS;
} else {
gl->fGetIntegerv(LOCAL_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &mGLMaxFragmentUniformVectors);
mGLMaxFragmentUniformVectors /= 4;
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS, &mGLMaxVertexUniformVectors);
mGLMaxVertexUniformVectors /= 4;
if (gl->HasES2Compatibility()) {
gl->fGetIntegerv(LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS, &mGLMaxFragmentUniformVectors);
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS, &mGLMaxVertexUniformVectors);
gl->fGetIntegerv(LOCAL_GL_MAX_VARYING_VECTORS, &mGLMaxVaryingVectors);
} else {
gl->fGetIntegerv(LOCAL_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &mGLMaxFragmentUniformVectors);
mGLMaxFragmentUniformVectors /= 4;
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS, &mGLMaxVertexUniformVectors);
mGLMaxVertexUniformVectors /= 4;
// we are now going to try to read GL_MAX_VERTEX_OUTPUT_COMPONENTS and GL_MAX_FRAGMENT_INPUT_COMPONENTS,
// however these constants only entered the OpenGL standard at OpenGL 3.2. So we will try reading,
// and check OpenGL error for INVALID_ENUM.
// we are now going to try to read GL_MAX_VERTEX_OUTPUT_COMPONENTS and GL_MAX_FRAGMENT_INPUT_COMPONENTS,
// however these constants only entered the OpenGL standard at OpenGL 3.2. So we will try reading,
// and check OpenGL error for INVALID_ENUM.
// before we start, we check that no error already occurred, to prevent hiding it in our subsequent error handling
error = gl->GetAndClearError();
if (error != LOCAL_GL_NO_ERROR) {
LogMessage("GL error 0x%x occurred during WebGL context initialization!", error);
return PR_FALSE;
}
// On the public_webgl list, "problematic GetParameter pnames" thread, the following formula was given:
// mGLMaxVaryingVectors = min (GL_MAX_VERTEX_OUTPUT_COMPONENTS, GL_MAX_FRAGMENT_INPUT_COMPONENTS) / 4
GLint maxVertexOutputComponents,
minFragmentInputComponents;
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_OUTPUT_COMPONENTS, &maxVertexOutputComponents);
gl->fGetIntegerv(LOCAL_GL_MAX_FRAGMENT_INPUT_COMPONENTS, &minFragmentInputComponents);
error = gl->fGetError();
switch (error) {
case LOCAL_GL_NO_ERROR:
mGLMaxVaryingVectors = NS_MIN(maxVertexOutputComponents, minFragmentInputComponents) / 4;
break;
case LOCAL_GL_INVALID_ENUM:
mGLMaxVaryingVectors = 16; // = 64/4, 64 is the min value for maxVertexOutputComponents in OpenGL 3.2 spec
break;
default:
// before we start, we check that no error already occurred, to prevent hiding it in our subsequent error handling
error = gl->GetAndClearError();
if (error != LOCAL_GL_NO_ERROR) {
LogMessage("GL error 0x%x occurred during WebGL context initialization!", error);
return PR_FALSE;
return false;
}
// On the public_webgl list, "problematic GetParameter pnames" thread, the following formula was given:
// mGLMaxVaryingVectors = min (GL_MAX_VERTEX_OUTPUT_COMPONENTS, GL_MAX_FRAGMENT_INPUT_COMPONENTS) / 4
GLint maxVertexOutputComponents,
minFragmentInputComponents;
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_OUTPUT_COMPONENTS, &maxVertexOutputComponents);
gl->fGetIntegerv(LOCAL_GL_MAX_FRAGMENT_INPUT_COMPONENTS, &minFragmentInputComponents);
error = gl->GetAndClearError();
switch (error) {
case LOCAL_GL_NO_ERROR:
mGLMaxVaryingVectors = NS_MIN(maxVertexOutputComponents, minFragmentInputComponents) / 4;
break;
case LOCAL_GL_INVALID_ENUM:
mGLMaxVaryingVectors = 16; // = 64/4, 64 is the min value for maxVertexOutputComponents in OpenGL 3.2 spec
break;
default:
LogMessage("GL error 0x%x occurred during WebGL context initialization!", error);
return false;
}
}
}

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

@ -3287,6 +3287,8 @@ pref("webgl.force_osmesa", false);
pref("webgl.osmesalib", "");
pref("webgl.verbose", false);
pref("webgl.prefer-native-gl", false);
pref("webgl.min_capability_mode", false);
pref("webgl.disable-extensions", false);
#ifdef XP_WIN
// The default TCP send window on Windows is too small, and autotuning only occurs on receive