Bug 1102667 - Fix our float texture/rb/fb support. - r=kamidphish

This commit is contained in:
jdashg 2014-11-21 15:04:08 -08:00
Родитель caad126bc8
Коммит d2aef2d9e2
7 изменённых файлов: 289 добавлений и 16 удалений

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

@ -1084,6 +1084,9 @@ public:
return mGLMaxVertexAttribs; return mGLMaxVertexAttribs;
} }
bool IsFormatValidForFB(GLenum sizedFormat) const;
protected: protected:
// Represents current status of the context with respect to context loss. // Represents current status of the context with respect to context loss.
// That is, whether the context is lost, and what part of the context loss // That is, whether the context is lost, and what part of the context loss
@ -1116,6 +1119,10 @@ protected:
// enable an extension. the extension should not be enabled before. // enable an extension. the extension should not be enabled before.
void EnableExtension(WebGLExtensionID ext); void EnableExtension(WebGLExtensionID ext);
// Enable an extension if it's supported. Return the extension on success.
WebGLExtensionBase* EnableSupportedExtension(JSContext* js,
WebGLExtensionID ext);
// returns true if the extension has been enabled by calling getExtension. // returns true if the extension has been enabled by calling getExtension.
bool IsExtensionEnabled(WebGLExtensionID ext) const; bool IsExtensionEnabled(WebGLExtensionID ext) const;

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

@ -186,6 +186,19 @@ CompareWebGLExtensionName(const nsACString& name, const char *other)
return name.Equals(other, nsCaseInsensitiveCStringComparator()); return name.Equals(other, nsCaseInsensitiveCStringComparator());
} }
WebGLExtensionBase*
WebGLContext::EnableSupportedExtension(JSContext* js, WebGLExtensionID ext)
{
if (!IsExtensionEnabled(ext)) {
if (!IsExtensionSupported(js, ext))
return nullptr;
EnableExtension(ext);
}
return mExtensions[ext];
}
void void
WebGLContext::GetExtension(JSContext *cx, const nsAString& aName, WebGLContext::GetExtension(JSContext *cx, const nsAString& aName,
JS::MutableHandle<JSObject*> aRetval, JS::MutableHandle<JSObject*> aRetval,
@ -201,8 +214,7 @@ WebGLContext::GetExtension(JSContext *cx, const nsAString& aName,
WebGLExtensionID ext = WebGLExtensionID::Unknown; WebGLExtensionID ext = WebGLExtensionID::Unknown;
// step 1: figure what extension is wanted // step 1: figure what extension is wanted
for (size_t i = 0; i < size_t(WebGLExtensionID::Max); i++) for (size_t i = 0; i < size_t(WebGLExtensionID::Max); i++) {
{
WebGLExtensionID extension = WebGLExtensionID(i); WebGLExtensionID extension = WebGLExtensionID(i);
if (CompareWebGLExtensionName(name, GetExtensionString(extension))) { if (CompareWebGLExtensionName(name, GetExtensionString(extension))) {
@ -211,8 +223,7 @@ WebGLContext::GetExtension(JSContext *cx, const nsAString& aName,
} }
} }
if (ext == WebGLExtensionID::Unknown) if (ext == WebGLExtensionID::Unknown) {
{
/** /**
* We keep backward compatibility for these deprecated vendor-prefixed * We keep backward compatibility for these deprecated vendor-prefixed
* alias. Do not add new ones anymore. Hide it behind the * alias. Do not add new ones anymore. Hide it behind the
@ -254,11 +265,27 @@ WebGLContext::GetExtension(JSContext *cx, const nsAString& aName,
} }
// step 3: if the extension hadn't been previously been created, create it now, thus enabling it // step 3: if the extension hadn't been previously been created, create it now, thus enabling it
if (!IsExtensionEnabled(ext)) { WebGLExtensionBase* extObj = EnableSupportedExtension(cx, ext);
EnableExtension(ext); if (!extObj) {
aRetval.set(nullptr);
return;
} }
aRetval.set(WebGLObjectAsJSObject(cx, mExtensions[ext].get(), rv)); // Step 4: Enable any implied extensions.
switch (ext) {
case WebGLExtensionID::OES_texture_float:
EnableSupportedExtension(cx, WebGLExtensionID::WEBGL_color_buffer_float);
break;
case WebGLExtensionID::OES_texture_half_float:
EnableSupportedExtension(cx, WebGLExtensionID::EXT_color_buffer_half_float);
break;
default:
break;
}
aRetval.set(WebGLObjectAsJSObject(cx, extObj, rv));
} }
void void

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

@ -23,8 +23,13 @@ WebGLExtensionColorBufferFloat::~WebGLExtensionColorBufferFloat()
bool bool
WebGLExtensionColorBufferFloat::IsSupported(const WebGLContext* context) WebGLExtensionColorBufferFloat::IsSupported(const WebGLContext* context)
{ {
return context->GL()->IsSupported(gl::GLFeature::renderbuffer_color_float) && gl::GLContext* gl = context->GL();
context->GL()->IsSupported(gl::GLFeature::frag_color_float);
// ANGLE supports this, but doesn't have a way to advertize its support,
// since it's compliant with WEBGL_color_buffer_float's clamping, but not
// EXT_color_buffer_float.
return gl->IsSupported(gl::GLFeature::renderbuffer_color_float) ||
gl->IsANGLE();
} }
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionColorBufferFloat) IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionColorBufferFloat)

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

@ -23,8 +23,10 @@ WebGLExtensionColorBufferHalfFloat::~WebGLExtensionColorBufferHalfFloat()
bool bool
WebGLExtensionColorBufferHalfFloat::IsSupported(const WebGLContext* context) WebGLExtensionColorBufferHalfFloat::IsSupported(const WebGLContext* context)
{ {
return context->GL()->IsSupported(gl::GLFeature::renderbuffer_color_half_float) && gl::GLContext* gl = context->GL();
context->GL()->IsSupported(gl::GLFeature::frag_color_float);
// ANGLE doesn't support ReadPixels from a RGBA16F with RGBA/FLOAT.
return gl->IsSupported(gl::GLFeature::renderbuffer_color_half_float);
} }
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionColorBufferHalfFloat) IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionColorBufferHalfFloat)

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

@ -283,6 +283,36 @@ IsValidFBORenderbufferStencilFormat(GLenum internalFormat)
return internalFormat == LOCAL_GL_STENCIL_INDEX8; return internalFormat == LOCAL_GL_STENCIL_INDEX8;
} }
bool
WebGLContext::IsFormatValidForFB(GLenum sizedFormat) const
{
switch (sizedFormat) {
case LOCAL_GL_ALPHA8:
case LOCAL_GL_LUMINANCE8:
case LOCAL_GL_LUMINANCE8_ALPHA8:
case LOCAL_GL_RGB8:
case LOCAL_GL_RGBA8:
case LOCAL_GL_RGB565:
case LOCAL_GL_RGB5_A1:
case LOCAL_GL_RGBA4:
return true;
case LOCAL_GL_SRGB8:
case LOCAL_GL_SRGB8_ALPHA8_EXT:
return IsExtensionEnabled(WebGLExtensionID::EXT_sRGB);
case LOCAL_GL_RGB32F:
case LOCAL_GL_RGBA32F:
return IsExtensionEnabled(WebGLExtensionID::WEBGL_color_buffer_float);
case LOCAL_GL_RGB16F:
case LOCAL_GL_RGBA16F:
return IsExtensionEnabled(WebGLExtensionID::EXT_color_buffer_half_float);
}
return false;
}
bool bool
WebGLFramebuffer::Attachment::IsComplete() const WebGLFramebuffer::Attachment::IsComplete() const
{ {
@ -301,23 +331,24 @@ WebGLFramebuffer::Attachment::IsComplete() const
MOZ_ASSERT(Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel)); MOZ_ASSERT(Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel));
const WebGLTexture::ImageInfo& imageInfo = const WebGLTexture::ImageInfo& imageInfo =
Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel); Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel);
GLenum internalformat = imageInfo.EffectiveInternalFormat().get(); GLenum sizedFormat = imageInfo.EffectiveInternalFormat().get();
if (mAttachmentPoint == LOCAL_GL_DEPTH_ATTACHMENT) if (mAttachmentPoint == LOCAL_GL_DEPTH_ATTACHMENT)
return IsValidFBOTextureDepthFormat(internalformat); return IsValidFBOTextureDepthFormat(sizedFormat);
if (mAttachmentPoint == LOCAL_GL_STENCIL_ATTACHMENT) if (mAttachmentPoint == LOCAL_GL_STENCIL_ATTACHMENT)
return false; // Textures can't have the correct format for stencil buffers return false; // Textures can't have the correct format for stencil buffers
if (mAttachmentPoint == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) { if (mAttachmentPoint == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
return IsValidFBOTextureDepthStencilFormat(internalformat); return IsValidFBOTextureDepthStencilFormat(sizedFormat);
} }
if (mAttachmentPoint >= LOCAL_GL_COLOR_ATTACHMENT0 && if (mAttachmentPoint >= LOCAL_GL_COLOR_ATTACHMENT0 &&
mAttachmentPoint <= FBAttachment(LOCAL_GL_COLOR_ATTACHMENT0 - 1 + mAttachmentPoint <= FBAttachment(LOCAL_GL_COLOR_ATTACHMENT0 - 1 +
WebGLContext::kMaxColorAttachments)) WebGLContext::kMaxColorAttachments))
{ {
return IsValidFBOTextureColorFormat(internalformat); WebGLContext* webgl = Texture()->Context();
return webgl->IsFormatValidForFB(sizedFormat);
} }
MOZ_ASSERT(false, "Invalid WebGL attachment point?"); MOZ_ASSERT(false, "Invalid WebGL attachment point?");
return false; return false;
@ -339,7 +370,8 @@ WebGLFramebuffer::Attachment::IsComplete() const
mAttachmentPoint <= FBAttachment(LOCAL_GL_COLOR_ATTACHMENT0 - 1 + mAttachmentPoint <= FBAttachment(LOCAL_GL_COLOR_ATTACHMENT0 - 1 +
WebGLContext::kMaxColorAttachments)) WebGLContext::kMaxColorAttachments))
{ {
return IsValidFBORenderbufferColorFormat(internalFormat); WebGLContext* webgl = Renderbuffer()->Context();
return webgl->IsFormatValidForFB(internalFormat);
} }
MOZ_ASSERT(false, "Invalid WebGL attachment point?"); MOZ_ASSERT(false, "Invalid WebGL attachment point?");
return false; return false;

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

@ -13,6 +13,7 @@ fail-if = (os == 'b2g')
[webgl-mochitest/test_fb_param_crash.html] [webgl-mochitest/test_fb_param_crash.html]
[webgl-mochitest/test_hidden_alpha.html] [webgl-mochitest/test_hidden_alpha.html]
skip-if = (os == 'b2g') || buildapp == 'mulet' # Mulet - bug 1093639 (crashes in libLLVM-3.0.so) skip-if = (os == 'b2g') || buildapp == 'mulet' # Mulet - bug 1093639 (crashes in libLLVM-3.0.so)
[webgl-mochitest/test_implicit_color_buffer_float.html]
[webgl-mochitest/test_highp_fs.html] [webgl-mochitest/test_highp_fs.html]
[webgl-mochitest/test_no_arr_points.html] [webgl-mochitest/test_no_arr_points.html]
skip-if = android_version == '10' #Android 2.3 aws only; bug 1030942 skip-if = android_version == '10' #Android 2.3 aws only; bug 1030942

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

@ -0,0 +1,199 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
</head>
<body>
<script>
var RGBA32F_EXT = 0x8814;
var RGBA16F_EXT = 0x881A; // Yep, it's really 4 and A.
var HALF_FLOAT_OES = 0x8D61;
function IsFormatValidForRB(gl, format) {
ok(!gl.getError(), 'Should have no errors here.');
var rb = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
gl.renderbufferStorage(gl.RENDERBUFFER, format, 4, 4);
var error = gl.getError();
if (error == gl.INVALID_ENUM)
return false;
ok(error == gl.NO_ERROR, 'Error should be INVALID_ENUM or NO_ERROR.');
return error == gl.NO_ERROR;
}
function IsFormatValidForTex(gl, format, type) {
ok(!gl.getError(), 'Should have no errors here.');
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, format, 4, 4, 0, format, type, null);
var error = gl.getError();
if (error == gl.INVALID_ENUM)
return false;
ok(error == gl.NO_ERROR, 'Error should be INVALID_ENUM or NO_ERROR.');
return error == gl.NO_ERROR;
}
function IsFormatValidForTexFB(gl, format, type) {
ok(!gl.getError(), 'Should have no errors here.');
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, format, 4, 4, 0, format, type, null);
var error = gl.getError();
if (error == gl.INVALID_ENUM)
return false;
ok(error == gl.NO_ERROR, 'Error should be INVALID_ENUM or NO_ERROR.');
var fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D,
tex, 0);
error = gl.getError();
ok(error == gl.NO_ERROR, 'Error should be NO_ERROR.');
var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
return status == gl.FRAMEBUFFER_COMPLETE;
}
function IsFormatValidForTexFBRead(gl, texFormat, texType, readType) {
ok(!gl.getError(), 'Should have no errors here.');
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, texFormat, 4, 4, 0, texFormat, texType,
null);
var error = gl.getError();
if (error == gl.INVALID_ENUM)
return false;
ok(error == gl.NO_ERROR, 'Error should be INVALID_ENUM or NO_ERROR.');
var fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D,
tex, 0);
error = gl.getError();
ok(error == gl.NO_ERROR, 'Error should be NO_ERROR.');
var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
if (status != gl.FRAMEBUFFER_COMPLETE)
return false;
var data;
switch (readType) {
case gl.UNSIGNED_BYTE:
data = new Uint8Array(4);
break;
case HALF_FLOAT_OES:
data = new Uint16Array(4);
break;
case gl.FLOAT:
data = new Float32Array(4);
break;
default:
throw 'Bad `readType`.';
}
gl.readPixels(0, 0, 1, 1, gl.RGBA, readType, data);
error = gl.getError();
return error == gl.NO_ERROR;
}
function TestColorBufferExt(gl, rbFormat, texFormat, texType, readType)
{
var isTexFBValid = IsFormatValidForTexFB(gl, texFormat, texType);
var isTexFBReadValid = IsFormatValidForTexFBRead(gl, texFormat, texType,
readType);
var isRBValid = IsFormatValidForRB(gl, rbFormat);
var validSubsetCount = isTexFBValid + isTexFBReadValid + isRBValid;
if (validSubsetCount) {
ok(isTexFBValid, 'If active, texture-fbs should work.');
ok(isTexFBReadValid, 'If active, reading texture-fbs should work.');
ok(isRBValid, 'If active, renderbuffers should work.');
}
return validSubsetCount == 3;
}
function TestImpliedExtension(gl, baseExtName, impliedExtName, rbFormat,
texFormat, texType, readType)
{
ok(true, '========');
ok(true, 'Testing if ' + baseExtName + ' implies ' + impliedExtName + '.');
ok(true, '--------');
var baseExt = gl.getExtension(baseExtName);
if (!baseExt) {
ok(!baseExt, 'Ext \'' + baseExtName + '\' can be unsupported.');
return;
}
var isTexValid = IsFormatValidForTex(gl, texFormat, texType);
ok(isTexValid, baseExtName + ' should allow float textures.');
if (!isTexValid)
return;
var isImplicitlyActive = TestColorBufferExt(gl, rbFormat, texFormat,
texType, readType);
if (isImplicitlyActive) {
ok(true, 'Activating ' + baseExtName + ' has implicitly activated ' +
impliedExtName + '.');
var impliedExt = gl.getExtension(impliedExtName);
ok(impliedExt, 'If ' + impliedExtName + ' is supported implicitly, it' +
' must be supported explicitly as well.');
return;
}
ok(true, 'Activating ' + baseExtName + ' has not implicitly activated ' +
impliedExtName + '.');
ok(true, '--------');
var impliedExt = gl.getExtension(impliedExtName);
if (!impliedExt) {
ok(true, impliedExtName + ' can be unsupported.');
return;
}
ok(true, 'Explicit activation of ' + impliedExtName + ' successful.');
var isFunctional = TestColorBufferExt(gl, rbFormat, texFormat, texType,
readType);
ok(isFunctional, impliedExtName + ' should be fully functional.');
}
(function() {
var canvas = document.createElement('canvas');
var gl = canvas.getContext('experimental-webgl');
if (!gl) {
ok(!gl, 'WebGL can be unsupported.');
return;
}
TestImpliedExtension(gl, 'OES_texture_float', 'WEBGL_color_buffer_float',
RGBA32F_EXT, gl.RGBA, gl.FLOAT, gl.FLOAT);
TestImpliedExtension(gl, 'OES_texture_half_float',
'EXT_color_buffer_half_float', RGBA16F_EXT, gl.RGBA,
HALF_FLOAT_OES, gl.FLOAT);
ok(true, '========');
ok(true, 'TEST COMPLETE');
})();
</script>
</body>
</html>