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

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

@ -63,6 +63,24 @@
#include "CheckedInt.h" #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 nsIDocShell;
class nsIPropertyBag; class nsIPropertyBag;
@ -415,6 +433,10 @@ public:
GLenum currentGLError; GLenum currentGLError;
UpdateWebGLErrorAndClearGLError(&currentGLError); UpdateWebGLErrorAndClearGLError(&currentGLError);
} }
bool MinCapabilityMode() const {
return mMinCapability;
}
protected: protected:
void SetDontKnowIfNeedFakeBlack() { void SetDontKnowIfNeedFakeBlack() {
@ -456,6 +478,8 @@ protected:
bool mResetLayer; bool mResetLayer;
bool mVerbose; bool mVerbose;
bool mOptionsFrozen; bool mOptionsFrozen;
bool mMinCapability;
bool mDisableExtensions;
WebGLuint mActiveTexture; WebGLuint mActiveTexture;
WebGLenum mWebGLError; WebGLenum mWebGLError;

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

@ -1900,7 +1900,61 @@ WebGLContext::GetParameter(PRUint32 pname, nsIVariant **retval)
NS_ENSURE_TRUE(wrval, NS_ERROR_FAILURE); NS_ENSURE_TRUE(wrval, NS_ERROR_FAILURE);
MakeContextCurrent(); 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) { switch (pname) {
// //
// String params // String params

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

@ -63,7 +63,11 @@ WebGLProgram::UpdateInfo(gl::GLContext *gl)
gl->fGetProgramiv(mName, LOCAL_GL_ACTIVE_ATTRIBUTES, &mAttribCount); gl->fGetProgramiv(mName, LOCAL_GL_ACTIVE_ATTRIBUTES, &mAttribCount);
GLint numVertexAttribs; 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.clear();
mAttribsInUse.resize(numVertexAttribs); mAttribsInUse.resize(numVertexAttribs);
@ -503,6 +507,9 @@ WebGLContext::InitAndValidateGL()
return PR_FALSE; return PR_FALSE;
} }
mMinCapability = Preferences::GetBool("webgl.min_capability_mode", false);
mDisableExtensions = Preferences::GetBool("webgl.disable-extensions", false);
mActiveTexture = 0; mActiveTexture = 0;
mWebGLError = LOCAL_GL_NO_ERROR; mWebGLError = LOCAL_GL_NO_ERROR;
@ -533,10 +540,14 @@ WebGLContext::InitAndValidateGL()
gl->fEnableVertexAttribArray(0); 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) { if (mGLMaxVertexAttribs < 8) {
LogMessage("GL_MAX_VERTEX_ATTRIBS: %d is < 8!", mGLMaxVertexAttribs); LogMessage("GL_MAX_VERTEX_ATTRIBS: %d is < 8!", mGLMaxVertexAttribs);
return PR_FALSE; return false;
} }
mAttribBuffers.SetLength(mGLMaxVertexAttribs); mAttribBuffers.SetLength(mGLMaxVertexAttribs);
@ -544,17 +555,30 @@ WebGLContext::InitAndValidateGL()
// Note: GL_MAX_TEXTURE_UNITS is fixed at 4 for most desktop hardware, // Note: GL_MAX_TEXTURE_UNITS is fixed at 4 for most desktop hardware,
// even though the hardware supports much more. The // even though the hardware supports much more. The
// GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS value is the accurate value. // 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) { if (mGLMaxTextureUnits < 8) {
LogMessage("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: %d is < 8!", mGLMaxTextureUnits); LogMessage("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: %d is < 8!", mGLMaxTextureUnits);
return PR_FALSE; return false;
} }
mBound2DTextures.SetLength(mGLMaxTextureUnits); mBound2DTextures.SetLength(mGLMaxTextureUnits);
mBoundCubeMapTextures.SetLength(mGLMaxTextureUnits); mBoundCubeMapTextures.SetLength(mGLMaxTextureUnits);
gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &mGLMaxTextureSize); if (MinCapabilityMode()) {
gl->fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mGLMaxCubeMapTextureSize); 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 #ifdef XP_MACOSX
if (gl->Vendor() == gl::GLContext::VendorIntel) { if (gl->Vendor() == gl::GLContext::VendorIntel) {
@ -564,48 +588,51 @@ WebGLContext::InitAndValidateGL()
} }
#endif #endif
gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS, &mGLMaxTextureImageUnits); if (MinCapabilityMode()) {
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mGLMaxVertexTextureImageUnits); mGLMaxFragmentUniformVectors = MINVALUE_GL_MAX_FRAGMENT_UNIFORM_VECTORS;
mGLMaxVertexUniformVectors = MINVALUE_GL_MAX_VERTEX_UNIFORM_VECTORS;
if (gl->HasES2Compatibility()) { mGLMaxVaryingVectors = MINVALUE_GL_MAX_VARYING_VECTORS;
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 { } else {
gl->fGetIntegerv(LOCAL_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &mGLMaxFragmentUniformVectors); if (gl->HasES2Compatibility()) {
mGLMaxFragmentUniformVectors /= 4; gl->fGetIntegerv(LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS, &mGLMaxFragmentUniformVectors);
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS, &mGLMaxVertexUniformVectors); gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS, &mGLMaxVertexUniformVectors);
mGLMaxVertexUniformVectors /= 4; 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, // 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, // however these constants only entered the OpenGL standard at OpenGL 3.2. So we will try reading,
// and check OpenGL error for INVALID_ENUM. // 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 // before we start, we check that no error already occurred, to prevent hiding it in our subsequent error handling
error = gl->GetAndClearError(); error = gl->GetAndClearError();
if (error != LOCAL_GL_NO_ERROR) { 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:
LogMessage("GL error 0x%x occurred during WebGL context initialization!", 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.osmesalib", "");
pref("webgl.verbose", false); pref("webgl.verbose", false);
pref("webgl.prefer-native-gl", false); pref("webgl.prefer-native-gl", false);
pref("webgl.min_capability_mode", false);
pref("webgl.disable-extensions", false);
#ifdef XP_WIN #ifdef XP_WIN
// The default TCP send window on Windows is too small, and autotuning only occurs on receive // The default TCP send window on Windows is too small, and autotuning only occurs on receive