Bug 584501 - another round of texture fixes - r=vladimir a=blocking2.0

This commit is contained in:
Benoit Jacob 2010-08-23 17:03:35 -04:00
Родитель b12e84a5aa
Коммит 707399e5dc
2 изменённых файлов: 88 добавлений и 20 удалений

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

@ -306,6 +306,11 @@ public:
return ErrorInvalidEnum("%s: invalid enum value 0x%x", info, enumvalue);
}
WebGLTexture *activeBoundTextureForTarget(WebGLenum target) {
return target == LOCAL_GL_TEXTURE_2D ? mBound2DTextures[mActiveTexture]
: mBoundCubeMapTextures[mActiveTexture];
}
already_AddRefed<CanvasLayer> GetCanvasLayer(CanvasLayer *aOldLayer,
LayerManager *aManager);
void MarkContextClean() { }
@ -334,15 +339,15 @@ protected:
PRBool mShaderValidation;
// some GL constants
PRUint32 mGLMaxVertexAttribs;
PRUint32 mGLMaxTextureUnits;
PRUint32 mGLMaxTextureSize;
PRUint32 mGLMaxCubeMapTextureSize;
PRUint32 mGLMaxTextureImageUnits;
PRUint32 mGLMaxVertexTextureImageUnits;
PRUint32 mGLMaxVaryingVectors;
PRUint32 mGLMaxFragmentUniformVectors;
PRUint32 mGLMaxVertexUniformVectors;
PRInt32 mGLMaxVertexAttribs;
PRInt32 mGLMaxTextureUnits;
PRInt32 mGLMaxTextureSize;
PRInt32 mGLMaxCubeMapTextureSize;
PRInt32 mGLMaxTextureImageUnits;
PRInt32 mGLMaxVertexTextureImageUnits;
PRInt32 mGLMaxVaryingVectors;
PRInt32 mGLMaxFragmentUniformVectors;
PRInt32 mGLMaxVertexUniformVectors;
PRBool SafeToCreateCanvas3DContext(nsHTMLCanvasElement *canvasElement);
PRBool InitAndValidateGL();

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

@ -63,6 +63,15 @@
using namespace mozilla;
template<typename T>
bool is_power_of_two(T x)
{
if (x <= 0)
return false;
else
return (x & (x-1)) == 0;
}
static PRBool BaseTypeAndSizeFromUniformType(WebGLenum uType, WebGLenum *baseType, WebGLint *unitSize);
/* Helper macros for when we're just wrapping a gl method, so that
@ -572,6 +581,9 @@ WebGLContext::CopyTexImage2D(WebGLenum target,
if (!CanvasUtils::CheckSaneSubrectSize(x,y,width, height, mWidth, mHeight))
return ErrorInvalidOperation("CopyTexImage2D: copied rectangle out of bounds");
if (!activeBoundTextureForTarget(target))
return ErrorInvalidOperation("copyTexImage2D: no texture bound to this target");
MakeContextCurrent();
gl->fCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
@ -1138,6 +1150,13 @@ WebGLContext::GenerateMipmap(WebGLenum target)
if (!ValidateTextureTargetEnum(target, "generateMipmap"))
return NS_OK;
WebGLTexture *tex = activeBoundTextureForTarget(target);
if (!(is_power_of_two(tex->width()) ||
is_power_of_two(tex->height()))) {
return ErrorInvalidOperation("generateMipmap: texture width and height must be powers of two");
}
MakeContextCurrent();
gl->fGenerateMipmap(target);
return NS_OK;
@ -3070,20 +3089,20 @@ WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum intern
{
switch (target) {
case LOCAL_GL_TEXTURE_2D:
break;
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
if (width != height)
return ErrorInvalidValue("texImage2D: with cube map targets, width and height must be equal");
break;
default:
return ErrorInvalidEnumInfo("texImage2D: target", target);
}
if (level < 0)
return ErrorInvalidValue("TexImage2D: level must be >= 0");
switch (internalformat) {
case LOCAL_GL_RGB:
case LOCAL_GL_RGBA:
@ -3092,11 +3111,30 @@ WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum intern
case LOCAL_GL_LUMINANCE_ALPHA:
break;
default:
return ErrorInvalidEnumInfo("TexImage2D: internal format", internalformat);
return ErrorInvalidEnumInfo("texImage2D: internal format", internalformat);
}
if (format != internalformat)
return ErrorInvalidOperation("texImage2D: format does not match internalformat");
WebGLsizei maxTextureSize = target == LOCAL_GL_TEXTURE_2D ? mGLMaxTextureSize : mGLMaxCubeMapTextureSize;
if (level < 0)
return ErrorInvalidValue("texImage2D: level must be >= 0");
if ((1 << level) > maxTextureSize)
return ErrorInvalidValue("texImage2D: 2^level exceeds maximum texture size");
if (width < 0 || height < 0)
return ErrorInvalidValue("TexImage2D: width and height must be >= 0");
return ErrorInvalidValue("texImage2D: width and height must be >= 0");
if (width > maxTextureSize || height > maxTextureSize)
return ErrorInvalidValue("texImage2D: width or height exceeds maximum texture size");
if (level >= 1) {
if (!(is_power_of_two(width) && is_power_of_two(height)))
return ErrorInvalidValue("texImage2D: with level > 0, width and height must be powers of two");
}
if (border != 0)
return ErrorInvalidValue("TexImage2D: border must be 0");
@ -3111,11 +3149,16 @@ WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum intern
return ErrorInvalidOperation("texImage2D: integer overflow computing the needed buffer size");
PRUint32 bytesNeeded = checked_bytesNeeded.value();
if (byteLength && byteLength < bytesNeeded)
return ErrorInvalidOperation("TexImage2D: not enough data for operation (need %d, have %d)",
bytesNeeded, byteLength);
WebGLTexture *tex = activeBoundTextureForTarget(target);
if (!tex)
return ErrorInvalidOperation("texImage2D: no texture is bound to this target");
MakeContextCurrent();
if (byteLength) {
@ -3133,8 +3176,7 @@ WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum intern
free(tempZeroData);
}
if (mBound2DTextures[mActiveTexture])
mBound2DTextures[mActiveTexture]->setDimensions(width, height);
tex->setDimensions(width, height);
return NS_OK;
}
@ -3208,11 +3250,24 @@ WebGLContext::TexSubImage2D_base(WebGLenum target, WebGLint level,
return ErrorInvalidEnumInfo("texSubImage2D: target", target);
}
WebGLsizei maxTextureSize = target == LOCAL_GL_TEXTURE_2D ? mGLMaxTextureSize : mGLMaxCubeMapTextureSize;
if (level < 0)
return ErrorInvalidValue("TexSubImage2D: level must be >= 0");
return ErrorInvalidValue("texSubImage2D: level must be >= 0");
if ((1 << level) > maxTextureSize)
return ErrorInvalidValue("texSubImage2D: 2^level exceeds maximum texture size");
if (width < 0 || height < 0)
return ErrorInvalidValue("TexSubImage2D: width and height must be > 0!");
return ErrorInvalidValue("texSubImage2D: width and height must be >= 0");
if (width > maxTextureSize || height > maxTextureSize)
return ErrorInvalidValue("texSubImage2D: width or height exceeds maximum texture size");
if (level >= 1) {
if (!(is_power_of_two(width) && is_power_of_two(height)))
return ErrorInvalidValue("texSubImage2D: with level > 0, width and height must be powers of two");
}
PRUint32 texelSize = 0;
if (!ValidateTexFormatAndType(format, type, &texelSize, "texSubImage2D"))
@ -3229,7 +3284,15 @@ WebGLContext::TexSubImage2D_base(WebGLenum target, WebGLint level,
PRUint32 bytesNeeded = checked_bytesNeeded.value();
if (byteLength < bytesNeeded)
return ErrorInvalidValue("TexSubImage2D: not enough data for operation (need %d, have %d)", bytesNeeded, byteLength);
return ErrorInvalidValue("texSubImage2D: not enough data for operation (need %d, have %d)", bytesNeeded, byteLength);
WebGLTexture *tex = activeBoundTextureForTarget(target);
if (!tex)
return ErrorInvalidOperation("texSubImage2D: no texture is bound to this target");
if (!CanvasUtils::CheckSaneSubrectSize(xoffset, yoffset, width, height, tex->width(), tex->height()))
return ErrorInvalidValue("texSubImage2D: subtexture rectangle out of bounds");
MakeContextCurrent();