зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1321450 - Fix Invalidate[Sub]Framebuffer. - r=ethlin
MozReview-Commit-ID: nrZP6E412k
This commit is contained in:
Родитель
a21a0e4cb3
Коммит
6e1880d435
|
@ -105,30 +105,119 @@ WebGL2Context::GetFramebufferAttachmentParameter(JSContext* cx,
|
|||
out_error);
|
||||
}
|
||||
|
||||
// Map attachments intended for the default buffer, to attachments for a non-
|
||||
// default buffer.
|
||||
////
|
||||
|
||||
static bool
|
||||
TranslateDefaultAttachments(const dom::Sequence<GLenum>& in, dom::Sequence<GLenum>* out)
|
||||
ValidateBackbufferAttachmentEnum(WebGLContext* webgl, const char* funcName,
|
||||
GLenum attachment)
|
||||
{
|
||||
for (size_t i = 0; i < in.Length(); i++) {
|
||||
switch (in[i]) {
|
||||
switch (attachment) {
|
||||
case LOCAL_GL_COLOR:
|
||||
if (!out->AppendElement(LOCAL_GL_COLOR_ATTACHMENT0, fallible)) {
|
||||
case LOCAL_GL_DEPTH:
|
||||
case LOCAL_GL_STENCIL:
|
||||
return true;
|
||||
|
||||
default:
|
||||
webgl->ErrorInvalidEnum("%s: attachment: invalid enum value 0x%x.",
|
||||
funcName, attachment);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
ValidateFramebufferAttachmentEnum(WebGLContext* webgl, const char* funcName,
|
||||
GLenum attachment)
|
||||
{
|
||||
if (attachment >= LOCAL_GL_COLOR_ATTACHMENT0 &&
|
||||
attachment <= webgl->LastColorAttachmentEnum())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (attachment) {
|
||||
case LOCAL_GL_DEPTH_ATTACHMENT:
|
||||
case LOCAL_GL_STENCIL_ATTACHMENT:
|
||||
case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
|
||||
return true;
|
||||
|
||||
default:
|
||||
webgl->ErrorInvalidEnum("%s: attachment: invalid enum value 0x%x.",
|
||||
funcName, attachment);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLContext::ValidateInvalidateFramebuffer(const char* funcName, GLenum target,
|
||||
const dom::Sequence<GLenum>& attachments,
|
||||
ErrorResult* const out_rv,
|
||||
std::vector<GLenum>* const scopedVector,
|
||||
GLsizei* const out_glNumAttachments,
|
||||
const GLenum** const out_glAttachments)
|
||||
{
|
||||
if (IsContextLost())
|
||||
return false;
|
||||
|
||||
gl->MakeCurrent();
|
||||
|
||||
if (!ValidateFramebufferTarget(target, funcName))
|
||||
return false;
|
||||
|
||||
const WebGLFramebuffer* fb;
|
||||
bool isDefaultFB;
|
||||
switch (target) {
|
||||
case LOCAL_GL_FRAMEBUFFER:
|
||||
case LOCAL_GL_DRAW_FRAMEBUFFER:
|
||||
fb = mBoundDrawFramebuffer;
|
||||
isDefaultFB = gl->Screen()->IsDrawFramebufferDefault();
|
||||
break;
|
||||
|
||||
case LOCAL_GL_READ_FRAMEBUFFER:
|
||||
fb = mBoundReadFramebuffer;
|
||||
isDefaultFB = gl->Screen()->IsReadFramebufferDefault();
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("GFX: Bad target.");
|
||||
}
|
||||
|
||||
*out_glNumAttachments = attachments.Length();
|
||||
*out_glAttachments = attachments.Elements();
|
||||
|
||||
if (fb) {
|
||||
for (const auto& attachment : attachments) {
|
||||
if (!ValidateFramebufferAttachmentEnum(this, funcName, attachment))
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
for (const auto& attachment : attachments) {
|
||||
if (!ValidateBackbufferAttachmentEnum(this, funcName, attachment))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isDefaultFB) {
|
||||
MOZ_ASSERT(scopedVector->empty());
|
||||
scopedVector->reserve(attachments.Length());
|
||||
for (const auto& attachment : attachments) {
|
||||
switch (attachment) {
|
||||
case LOCAL_GL_COLOR:
|
||||
scopedVector->push_back(LOCAL_GL_COLOR_ATTACHMENT0);
|
||||
break;
|
||||
|
||||
case LOCAL_GL_DEPTH:
|
||||
if (!out->AppendElement(LOCAL_GL_DEPTH_ATTACHMENT, fallible)) {
|
||||
return false;
|
||||
}
|
||||
scopedVector->push_back(LOCAL_GL_DEPTH_ATTACHMENT);
|
||||
break;
|
||||
|
||||
case LOCAL_GL_STENCIL:
|
||||
if (!out->AppendElement(LOCAL_GL_STENCIL_ATTACHMENT, fallible)) {
|
||||
return false;
|
||||
}
|
||||
scopedVector->push_back(LOCAL_GL_STENCIL_ATTACHMENT);
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
*out_glNumAttachments = scopedVector->size();
|
||||
*out_glAttachments = scopedVector->data();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,59 +231,27 @@ WebGL2Context::InvalidateFramebuffer(GLenum target,
|
|||
{
|
||||
const char funcName[] = "invalidateSubFramebuffer";
|
||||
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (!ValidateFramebufferTarget(target, funcName))
|
||||
return;
|
||||
|
||||
const WebGLFramebuffer* fb;
|
||||
bool isDefaultFB;
|
||||
switch (target) {
|
||||
case LOCAL_GL_FRAMEBUFFER:
|
||||
case LOCAL_GL_DRAW_FRAMEBUFFER:
|
||||
fb = mBoundDrawFramebuffer;
|
||||
isDefaultFB = gl->Screen()->IsDrawFramebufferDefault();
|
||||
break;
|
||||
|
||||
case LOCAL_GL_READ_FRAMEBUFFER:
|
||||
fb = mBoundReadFramebuffer;
|
||||
isDefaultFB = gl->Screen()->IsReadFramebufferDefault();
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("GFX: Bad target.");
|
||||
}
|
||||
|
||||
const bool badColorAttachmentIsInvalidOp = true;
|
||||
for (size_t i = 0; i < attachments.Length(); i++) {
|
||||
if (!ValidateFramebufferAttachment(fb, attachments[i], funcName,
|
||||
badColorAttachmentIsInvalidOp))
|
||||
std::vector<GLenum> scopedVector;
|
||||
GLsizei glNumAttachments;
|
||||
const GLenum* glAttachments;
|
||||
if (!ValidateInvalidateFramebuffer(funcName, target, attachments, &rv, &scopedVector,
|
||||
&glNumAttachments, &glAttachments))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// InvalidateFramebuffer is a hint to the driver. Should be OK to
|
||||
// skip calls if not supported, for example by OSX 10.9 GL
|
||||
// drivers.
|
||||
if (!gl->IsSupported(gl::GLFeature::invalidate_framebuffer))
|
||||
return;
|
||||
////
|
||||
|
||||
if (!fb && !isDefaultFB) {
|
||||
dom::Sequence<GLenum> tmpAttachments;
|
||||
if (!TranslateDefaultAttachments(attachments, &tmpAttachments)) {
|
||||
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
// Some drivers (like OSX 10.9 GL) just don't support invalidate_framebuffer.
|
||||
const bool useFBInvalidation = (mAllowFBInvalidation &&
|
||||
gl->IsSupported(gl::GLFeature::invalidate_framebuffer));
|
||||
if (useFBInvalidation) {
|
||||
gl->fInvalidateFramebuffer(target, glNumAttachments, glAttachments);
|
||||
return;
|
||||
}
|
||||
|
||||
gl->fInvalidateFramebuffer(target, tmpAttachments.Length(),
|
||||
tmpAttachments.Elements());
|
||||
} else {
|
||||
gl->fInvalidateFramebuffer(target, attachments.Length(), attachments.Elements());
|
||||
}
|
||||
// Use clear instead?
|
||||
// No-op for now.
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -204,65 +261,28 @@ WebGL2Context::InvalidateSubFramebuffer(GLenum target, const dom::Sequence<GLenu
|
|||
{
|
||||
const char funcName[] = "invalidateSubFramebuffer";
|
||||
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (!ValidateFramebufferTarget(target, funcName))
|
||||
return;
|
||||
|
||||
if (width < 0 || height < 0) {
|
||||
ErrorInvalidValue("%s: width and height must be >= 0.", funcName);
|
||||
return;
|
||||
}
|
||||
|
||||
const WebGLFramebuffer* fb;
|
||||
bool isDefaultFB;
|
||||
switch (target) {
|
||||
case LOCAL_GL_FRAMEBUFFER:
|
||||
case LOCAL_GL_DRAW_FRAMEBUFFER:
|
||||
fb = mBoundDrawFramebuffer;
|
||||
isDefaultFB = gl->Screen()->IsDrawFramebufferDefault();
|
||||
break;
|
||||
|
||||
case LOCAL_GL_READ_FRAMEBUFFER:
|
||||
fb = mBoundReadFramebuffer;
|
||||
isDefaultFB = gl->Screen()->IsReadFramebufferDefault();
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("GFX: Bad target.");
|
||||
}
|
||||
|
||||
const bool badColorAttachmentIsInvalidOp = true;
|
||||
for (size_t i = 0; i < attachments.Length(); i++) {
|
||||
if (!ValidateFramebufferAttachment(fb, attachments[i], funcName,
|
||||
badColorAttachmentIsInvalidOp))
|
||||
std::vector<GLenum> scopedVector;
|
||||
GLsizei glNumAttachments;
|
||||
const GLenum* glAttachments;
|
||||
if (!ValidateInvalidateFramebuffer(funcName, target, attachments, &rv, &scopedVector,
|
||||
&glNumAttachments, &glAttachments))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// InvalidateFramebuffer is a hint to the driver. Should be OK to
|
||||
// skip calls if not supported, for example by OSX 10.9 GL
|
||||
// drivers.
|
||||
if (!gl->IsSupported(gl::GLFeature::invalidate_framebuffer))
|
||||
return;
|
||||
////
|
||||
|
||||
if (!fb && !isDefaultFB) {
|
||||
dom::Sequence<GLenum> tmpAttachments;
|
||||
if (!TranslateDefaultAttachments(attachments, &tmpAttachments)) {
|
||||
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
// Some drivers (like OSX 10.9 GL) just don't support invalidate_framebuffer.
|
||||
const bool useFBInvalidation = (mAllowFBInvalidation &&
|
||||
gl->IsSupported(gl::GLFeature::invalidate_framebuffer));
|
||||
if (useFBInvalidation) {
|
||||
gl->fInvalidateSubFramebuffer(target, glNumAttachments, glAttachments, x, y,
|
||||
width, height);
|
||||
return;
|
||||
}
|
||||
|
||||
gl->fInvalidateSubFramebuffer(target, tmpAttachments.Length(),
|
||||
tmpAttachments.Elements(), x, y, width, height);
|
||||
} else {
|
||||
gl->fInvalidateSubFramebuffer(target, attachments.Length(),
|
||||
attachments.Elements(), x, y, width, height);
|
||||
}
|
||||
// Use clear instead?
|
||||
// No-op for now.
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -126,6 +126,7 @@ WebGLContext::WebGLContext()
|
|||
, mNeedsFakeNoDepth(false)
|
||||
, mNeedsFakeNoStencil(false)
|
||||
, mNeedsEmulatedLoneDepthStencil(false)
|
||||
, mAllowFBInvalidation(gfxPrefs::WebGLFBInvalidation())
|
||||
{
|
||||
mGeneration = 0;
|
||||
mInvalidated = false;
|
||||
|
|
|
@ -536,11 +536,6 @@ public:
|
|||
GLenum texImageTarget, WebGLTexture* tex,
|
||||
GLint level);
|
||||
|
||||
// Framebuffer validation
|
||||
bool ValidateFramebufferAttachment(const WebGLFramebuffer* fb, GLenum attachment,
|
||||
const char* funcName,
|
||||
bool badColorAttachmentIsInvalidOp = false);
|
||||
|
||||
void FrontFace(GLenum mode);
|
||||
already_AddRefed<WebGLActiveInfo> GetActiveAttrib(const WebGLProgram& prog,
|
||||
GLuint index);
|
||||
|
@ -1687,6 +1682,12 @@ protected:
|
|||
RefPtr<const webgl::LinkedProgramInfo> mActiveProgramLinkInfo;
|
||||
|
||||
bool ValidateFramebufferTarget(GLenum target, const char* const info);
|
||||
bool ValidateInvalidateFramebuffer(const char* funcName, GLenum target,
|
||||
const dom::Sequence<GLenum>& attachments,
|
||||
ErrorResult* const out_rv,
|
||||
std::vector<GLenum>* const scopedVector,
|
||||
GLsizei* const out_glNumAttachments,
|
||||
const GLenum** const out_glAttachments);
|
||||
|
||||
WebGLRefPtr<WebGLFramebuffer> mBoundDrawFramebuffer;
|
||||
WebGLRefPtr<WebGLFramebuffer> mBoundReadFramebuffer;
|
||||
|
@ -1828,6 +1829,8 @@ protected:
|
|||
bool mNeedsFakeNoStencil;
|
||||
bool mNeedsEmulatedLoneDepthStencil;
|
||||
|
||||
const bool mAllowFBInvalidation;
|
||||
|
||||
bool Has64BitTimestamps() const;
|
||||
|
||||
struct ScopedMaskWorkaround {
|
||||
|
|
|
@ -196,50 +196,6 @@ WebGLContext::ValidateDrawModeEnum(GLenum mode, const char* info)
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLContext::ValidateFramebufferAttachment(const WebGLFramebuffer* fb, GLenum attachment,
|
||||
const char* funcName,
|
||||
bool badColorAttachmentIsInvalidOp)
|
||||
{
|
||||
if (!fb) {
|
||||
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)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (attachment >= LOCAL_GL_COLOR_ATTACHMENT0 &&
|
||||
attachment <= LastColorAttachmentEnum())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (badColorAttachmentIsInvalidOp &&
|
||||
attachment >= LOCAL_GL_COLOR_ATTACHMENT0)
|
||||
{
|
||||
const uint32_t offset = attachment - LOCAL_GL_COLOR_ATTACHMENT0;
|
||||
ErrorInvalidOperation("%s: Bad color attachment: COLOR_ATTACHMENT%u. (0x%04x)",
|
||||
funcName, offset, attachment);
|
||||
} else {
|
||||
ErrorInvalidEnum("%s: attachment: Bad attachment 0x%x.", funcName, attachment);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLContext::ValidateUniformLocation(WebGLUniformLocation* loc, const char* funcName)
|
||||
{
|
||||
|
|
|
@ -608,6 +608,7 @@ private:
|
|||
DECL_GFX_PREF(Live, "webgl.prefer-16bpp", WebGLPrefer16bpp, bool, false);
|
||||
DECL_GFX_PREF(Live, "webgl.restore-context-when-visible", WebGLRestoreWhenVisible, bool, true);
|
||||
DECL_GFX_PREF(Live, "webgl.allow-immediate-queries", WebGLImmediateQueries, bool, false);
|
||||
DECL_GFX_PREF(Live, "webgl.allow-fb-invalidation", WebGLFBInvalidation, bool, false);
|
||||
|
||||
DECL_GFX_PREF(Live, "webgl.webgl2-compat-mode", WebGL2CompatMode, bool, false);
|
||||
|
||||
|
|
|
@ -4494,6 +4494,7 @@ pref("webgl.enable-privileged-extensions", false);
|
|||
pref("webgl.bypass-shader-validation", false);
|
||||
pref("webgl.disable-fail-if-major-performance-caveat", false);
|
||||
pref("webgl.disable-DOM-blit-uploads", false);
|
||||
pref("webgl.allow-fb-invalidation", false);
|
||||
pref("webgl.webgl2-compat-mode", false);
|
||||
|
||||
pref("webgl.enable-webgl2", true);
|
||||
|
|
Загрузка…
Ссылка в новой задаче