WebGL2: Implement invalidateFramebuffer and invalidateSubFramebuffer (bug 1076456, r=jgilbert).

--HG--
extra : rebase_source : 5ce9c956475388896fe193ca37c9595978adf15c
This commit is contained in:
David Anderson 2014-10-14 14:49:49 -07:00
parent ab72b35cb5
commit e8609c1ba4
12 changed files with 211 additions and 7 deletions

View File

@ -78,7 +78,8 @@ WebGLContext::InitWebGL2()
};
const GLFeature sFeatureRequiredArr[] = {
GLFeature::instanced_non_arrays,
GLFeature::transform_feedback2
GLFeature::transform_feedback2,
GLFeature::invalidate_framebuffer
};
// check WebGL extensions that are supposed to be natively supported

View File

@ -32,17 +32,73 @@ WebGL2Context::GetInternalformatParameter(JSContext*, GLenum target, GLenum inte
MOZ_CRASH("Not Implemented.");
}
void
WebGL2Context::InvalidateFramebuffer(GLenum target, const dom::Sequence<GLenum>& attachments)
// Map attachments intended for the default buffer, to attachments for a non-
// default buffer.
static void
TranslateDefaultAttachments(const dom::Sequence<GLenum>& in, dom::Sequence<GLenum>* out)
{
MOZ_CRASH("Not Implemented.");
for (size_t i = 0; i < in.Length(); i++) {
switch (in[i]) {
case LOCAL_GL_COLOR:
out->AppendElement(LOCAL_GL_COLOR_ATTACHMENT0);
break;
case LOCAL_GL_DEPTH:
out->AppendElement(LOCAL_GL_DEPTH_ATTACHMENT);
break;
case LOCAL_GL_STENCIL:
out->AppendElement(LOCAL_GL_STENCIL_ATTACHMENT);
break;
}
}
}
void
WebGL2Context::InvalidateSubFramebuffer (GLenum target, const dom::Sequence<GLenum>& attachments,
GLint x, GLint y, GLsizei width, GLsizei height)
WebGL2Context::InvalidateFramebuffer(GLenum target, const dom::Sequence<GLenum>& attachments)
{
MOZ_CRASH("Not Implemented.");
if (IsContextLost())
return;
MakeContextCurrent();
if (target != LOCAL_GL_FRAMEBUFFER)
return ErrorInvalidEnumInfo("invalidateFramebuffer: target", target);
for (size_t i = 0; i < attachments.Length(); i++) {
if (!ValidateFramebufferAttachment(attachments[i], "invalidateFramebuffer"))
return;
}
if (!mBoundFramebuffer && !gl->IsDrawingToDefaultFramebuffer()) {
dom::Sequence<GLenum> tmpAttachments;
TranslateDefaultAttachments(attachments, &tmpAttachments);
gl->fInvalidateFramebuffer(target, tmpAttachments.Length(), tmpAttachments.Elements());
} else {
gl->fInvalidateFramebuffer(target, attachments.Length(), attachments.Elements());
}
}
void
WebGL2Context::InvalidateSubFramebuffer(GLenum target, const dom::Sequence<GLenum>& attachments,
GLint x, GLint y, GLsizei width, GLsizei height)
{
if (IsContextLost())
return;
MakeContextCurrent();
if (target != LOCAL_GL_FRAMEBUFFER)
return ErrorInvalidEnumInfo("invalidateFramebuffer: target", target);
for (size_t i = 0; i < attachments.Length(); i++) {
if (!ValidateFramebufferAttachment(attachments[i], "invalidateSubFramebuffer"))
return;
}
if (!mBoundFramebuffer && !gl->IsDrawingToDefaultFramebuffer()) {
dom::Sequence<GLenum> tmpAttachments;
TranslateDefaultAttachments(attachments, &tmpAttachments);
gl->fInvalidateSubFramebuffer(target, tmpAttachments.Length(), tmpAttachments.Elements(),
x, y, width, height);
} else {
gl->fInvalidateSubFramebuffer(target, attachments.Length(), attachments.Elements(),
x, y, width, height);
}
}
void

View File

@ -339,6 +339,18 @@ bool WebGLContext::ValidateGLSLString(const nsAString& string, const char *info)
bool
WebGLContext::ValidateFramebufferAttachment(GLenum attachment, const char* funcName)
{
if (!mBoundFramebuffer) {
switch (attachment) {
case LOCAL_GL_COLOR:
case LOCAL_GL_DEPTH:
case LOCAL_GL_STENCIL:
return true;
default:
ErrorInvalidEnum("%s: attachment: invalid enum value 0x%x.", funcName, attachment);
return false;
}
}
if (attachment == LOCAL_GL_DEPTH_ATTACHMENT ||
attachment == LOCAL_GL_STENCIL_ATTACHMENT ||
attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)

View File

@ -24,3 +24,5 @@ skip-if = toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests
skip-if = toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests pass except for one on armv6 tests
[webgl-mochitest/test_webgl2_not_exposed.html]
skip-if = toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests pass except for one on armv6 tests
[webgl-mochitest/test_webgl2_invalidate_framebuffer.html]
skip-if = toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests pass except for one on armv6 tests

View File

@ -0,0 +1,27 @@
<!DOCTYPE HTML>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>WebGL2 test: Framebuffers</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
<script src="driver-info.js"></script>
<script src="webgl-util.js"></script>
<body>
<canvas id="c" width="64" height="64"></canvas>
<script>
WebGLUtil.withWebGL2('c', function (gl) {
gl.invalidateFramebuffer(gl.FRAMEBUFFER, [gl.COLOR]);
ok(gl.getError() == 0, 'invalidateFramebuffer');
gl.invalidateSubFramebuffer(gl.FRAMEBUFFER, [gl.COLOR], 0, 0, 64, 64);
ok(gl.getError() == 0, 'invalidateSubFramebuffer');
gl.invalidateFramebuffer(gl.FRAMEBUFFER, [gl.GL_COLOR_ATTACHMENT0]);
ok(gl.getError() == gl.INVALID_ENUM, 'invalidateFrameBuffer should fail with GL_COLOR_ATTACHMENT on the default framebuffer');
}, function () {
SimpleTest.finish();
});
SimpleTest.waitForExplicitFinish();
</script>

View File

@ -58,6 +58,44 @@ WebGLUtil = (function() {
return gl;
}
function withWebGL2(canvasId, callback, onFinished) {
var prefArrArr = [
['webgl.force-enabled', true],
['webgl.disable-angle', true],
['webgl.enable-prototype-webgl2', true],
];
var prefEnv = {'set': prefArrArr};
SpecialPowers.pushPrefEnv(prefEnv, function() {
var canvas = document.getElementById(canvasId);
var gl = null;
try {
gl = canvas.getContext('webgl2');
} catch(e) {}
if (!gl) {
try {
gl = canvas.getContext('experimental-webgl2');
} catch(e) {}
}
if (!gl) {
todo(false, 'WebGL2 is not supported');
onFinished();
return;
}
function errorFunc(str) {
ok(false, 'Error: ' + str);
}
setErrorFunc(errorFunc);
setWarningFunc(errorFunc);
callback(gl);
onFinished();
});
}
function getContentFromElem(elem) {
var str = "";
var k = elem.firstChild;
@ -125,6 +163,7 @@ WebGLUtil = (function() {
setWarningFunc: setWarningFunc,
getWebGL: getWebGL,
withWebGL2: withWebGL2,
createShaderById: createShaderById,
createProgramByIds: createProgramByIds,
};

View File

@ -84,6 +84,7 @@ static const char *sExtensionNames[] = {
"GL_ARB_framebuffer_sRGB",
"GL_ARB_half_float_pixel",
"GL_ARB_instanced_arrays",
"GL_ARB_invalidate_subdata",
"GL_ARB_map_buffer_range",
"GL_ARB_occlusion_query2",
"GL_ARB_pixel_buffer_object",
@ -1356,6 +1357,21 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
}
}
if (IsSupported(GLFeature::invalidate_framebuffer)) {
SymLoadStruct invSymbols[] = {
{ (PRFuncPtr *) &mSymbols.fInvalidateFramebuffer, { "InvalidateFramebuffer", nullptr } },
{ (PRFuncPtr *) &mSymbols.fInvalidateSubFramebuffer, { "InvalidateSubFramebuffer", nullptr } },
END_SYMBOLS
};
if (!LoadSymbols(&invSymbols[0], trygl, prefix)) {
NS_ERROR("GL supports framebuffer invalidation without supplying its functions.");
MarkUnsupported(GLFeature::invalidate_framebuffer);
ClearSymbols(invSymbols);
}
}
if (IsExtensionSupported(KHR_debug)) {
SymLoadStruct extSymbols[] = {
{ (PRFuncPtr*) &mSymbols.fDebugMessageControl, { "DebugMessageControl", "DebugMessageControlKHR", nullptr } },

View File

@ -100,6 +100,7 @@ MOZ_BEGIN_ENUM_CLASS(GLFeature)
gpu_shader4,
instanced_arrays,
instanced_non_arrays,
invalidate_framebuffer,
map_buffer_range,
occlusion_query,
occlusion_query_boolean,
@ -367,6 +368,7 @@ public:
ARB_framebuffer_sRGB,
ARB_half_float_pixel,
ARB_instanced_arrays,
ARB_invalidate_subdata,
ARB_map_buffer_range,
ARB_occlusion_query2,
ARB_pixel_buffer_object,
@ -890,6 +892,20 @@ public:
raw_fBindFramebuffer(target, framebuffer);
}
void fInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments) {
BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fInvalidateFramebuffer);
mSymbols.fInvalidateFramebuffer(target, numAttachments, attachments);
AFTER_GL_CALL;
}
void fInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height) {
BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fInvalidateSubFramebuffer);
mSymbols.fInvalidateSubFramebuffer(target, numAttachments, attachments, x, y, width, height);
AFTER_GL_CALL;
}
void fBindTexture(GLenum target, GLuint texture) {
BEFORE_GL_CALL;
mSymbols.fBindTexture(target, texture);
@ -3537,6 +3553,10 @@ public:
bool WorkAroundDriverBugs() const { return mWorkAroundDriverBugs; }
bool IsDrawingToDefaultFramebuffer() {
return Screen()->IsDrawFramebufferDefault();
}
protected:
nsRefPtr<TextureGarbageBin> mTexGarbageBin;

View File

@ -288,6 +288,15 @@ static const FeatureInfo sFeatureInfoArr[] = {
* has no such restriction.
*/
},
{
"invalidate_framebuffer",
430, // OpenGL version
300, // OpenGL ES version
GLContext::ARB_invalidate_subdata,
{
GLContext::Extensions_End
}
},
{
"map_buffer_range",
300, // OpenGL version

View File

@ -334,6 +334,11 @@ struct GLContextSymbols
typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGE) (GLenum target, GLenum internalFormat, GLsizei width, GLsizei height);
PFNGLRENDERBUFFERSTORAGE fRenderbufferStorage;
typedef void (GLAPIENTRY * PFNINVALIDATEFRAMEBUFFER) (GLenum target, GLsizei numAttachments, const GLenum* attachments);
PFNINVALIDATEFRAMEBUFFER fInvalidateFramebuffer;
typedef void (GLAPIENTRY * PFNINVALIDATESUBFRAMEBUFFER) (GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height);
PFNINVALIDATESUBFRAMEBUFFER fInvalidateSubFramebuffer;
// These functions are only used by Skia/GL in desktop mode.
// Other parts of Gecko should avoid using these
typedef void (GLAPIENTRY * PFNGLCLIENTACTIVETEXTURE) (GLenum texture);

View File

@ -529,6 +529,20 @@ GLScreenBuffer::Readback(SharedSurface* src, gfx::DataSourceSurface* dest)
}
}
bool
GLScreenBuffer::IsDrawFramebufferDefault() const
{
if (!mDraw)
return IsReadFramebufferDefault();
return mDraw->mFB == 0;
}
bool
GLScreenBuffer::IsReadFramebufferDefault() const
{
return SharedSurf()->mAttachType == AttachmentType::Screen;
}
////////////////////////////////////////////////////////////////////////
// DrawBuffer

View File

@ -261,6 +261,9 @@ public:
void BindFB_Internal(GLuint fb);
void BindDrawFB_Internal(GLuint fb);
void BindReadFB_Internal(GLuint fb);
bool IsDrawFramebufferDefault() const;
bool IsReadFramebufferDefault() const;
};
} // namespace gl