bug 843667 - implement WEBGL_draw_buffers and add the user preference webgl.enable-draft-extensions - r=bjacob

This commit is contained in:
Guillaume Abadie 2013-06-21 19:44:17 -04:00
parent 6910532ccd
commit 69a846c1a8
13 changed files with 620 additions and 106 deletions

View File

@ -179,6 +179,8 @@ WebGLContext::WebGLContext()
mGLMaxVaryingVectors = 0;
mGLMaxFragmentUniformVectors = 0;
mGLMaxVertexUniformVectors = 0;
mGLMaxColorAttachments = 1;
mGLMaxDrawBuffers = 1;
// See OpenGL ES 2.0.25 spec, 6.2 State Tables, table 6.13
mPixelStorePackAlignment = 4;
@ -1019,7 +1021,16 @@ bool WebGLContext::IsExtensionSupported(JSContext *cx, WebGLExtensionID ext) con
break;
}
MOZ_NOT_REACHED("Query for unknown extension.");
if (Preferences::GetBool("webgl.enable-draft-extensions", false)) {
switch (ext) {
case WEBGL_draw_buffers:
return WebGLExtensionDrawBuffers::IsSupported(this);
default:
// For warnings-as-errors.
break;
}
}
return false;
}
@ -1096,6 +1107,10 @@ WebGLContext::GetExtension(JSContext *cx, const nsAString& aName, ErrorResult& r
{
ext = WEBGL_depth_texture;
}
else if (CompareWebGLExtensionName(name, "WEBGL_draw_buffers"))
{
ext = WEBGL_draw_buffers;
}
if (ext == WebGLExtensionID_unknown_extension) {
return nullptr;
@ -1143,6 +1158,9 @@ WebGLContext::GetExtension(JSContext *cx, const nsAString& aName, ErrorResult& r
case OES_texture_float_linear:
obj = new WebGLExtensionTextureFloatLinear(this);
break;
case WEBGL_draw_buffers:
obj = new WebGLExtensionDrawBuffers(this);
break;
default:
MOZ_ASSERT(false, "should not get there.");
}
@ -1156,6 +1174,8 @@ WebGLContext::GetExtension(JSContext *cx, const nsAString& aName, ErrorResult& r
void
WebGLContext::ClearScreen()
{
bool colorAttachmentsMask[WebGLContext::sMaxColorAttachments] = {false};
MakeContextCurrent();
ScopedBindFramebuffer autoFB(gl, 0);
@ -1165,7 +1185,9 @@ WebGLContext::ClearScreen()
if (mOptions.stencil)
clearMask |= LOCAL_GL_STENCIL_BUFFER_BIT;
ForceClearFramebufferWithDefaultValues(clearMask);
colorAttachmentsMask[0] = true;
ForceClearFramebufferWithDefaultValues(clearMask, colorAttachmentsMask);
mIsScreenCleared = true;
}
@ -1177,13 +1199,16 @@ static bool IsSameFloat(float a, float b) {
#endif
void
WebGLContext::ForceClearFramebufferWithDefaultValues(GLbitfield mask)
WebGLContext::ForceClearFramebufferWithDefaultValues(GLbitfield mask, const bool colorAttachmentsMask[sMaxColorAttachments])
{
MakeContextCurrent();
bool initializeColorBuffer = 0 != (mask & LOCAL_GL_COLOR_BUFFER_BIT);
bool initializeDepthBuffer = 0 != (mask & LOCAL_GL_DEPTH_BUFFER_BIT);
bool initializeStencilBuffer = 0 != (mask & LOCAL_GL_STENCIL_BUFFER_BIT);
bool drawBuffersIsEnabled = IsExtensionEnabled(WEBGL_draw_buffers);
GLenum currentDrawBuffers[WebGLContext::sMaxColorAttachments];
// Fun GL fact: No need to worry about the viewport here, glViewport is just
// setting up a coordinates transformation, it doesn't affect glClear at all.
@ -1248,6 +1273,24 @@ WebGLContext::ForceClearFramebufferWithDefaultValues(GLbitfield mask)
gl->fDisable(LOCAL_GL_SCISSOR_TEST);
if (initializeColorBuffer) {
if (drawBuffersIsEnabled) {
GLenum drawBuffersCommand[WebGLContext::sMaxColorAttachments] = { LOCAL_GL_NONE };
for(int32_t i = 0; i < mGLMaxDrawBuffers; i++) {
GLint temp;
gl->fGetIntegerv(LOCAL_GL_DRAW_BUFFER0 + i, &temp);
currentDrawBuffers[i] = temp;
if (colorAttachmentsMask[i]) {
drawBuffersCommand[i] = LOCAL_GL_COLOR_ATTACHMENT0 + i;
}
}
gl->fDrawBuffers(mGLMaxDrawBuffers, drawBuffersCommand);
}
gl->fColorMask(1, 1, 1, 1);
gl->fClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}
@ -1274,6 +1317,10 @@ WebGLContext::ForceClearFramebufferWithDefaultValues(GLbitfield mask)
// Restore GL state after clearing.
if (initializeColorBuffer) {
if (drawBuffersIsEnabled) {
gl->fDrawBuffers(mGLMaxDrawBuffers, currentDrawBuffers);
}
gl->fColorMask(mColorWriteMask[0],
mColorWriteMask[1],
mColorWriteMask[2],
@ -1515,6 +1562,8 @@ WebGLContext::GetSupportedExtensions(JSContext *cx, Nullable< nsTArray<nsString>
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_depth_texture"));
if (IsExtensionSupported(cx, WEBGL_depth_texture))
arr.AppendElement(NS_LITERAL_STRING("WEBGL_depth_texture"));
if (IsExtensionSupported(cx, WEBGL_draw_buffers))
arr.AppendElement(NS_LITERAL_STRING("WEBGL_draw_buffers"));
}
//

View File

@ -127,6 +127,7 @@ class WebGLContext :
friend class WebGLExtensionCompressedTextureATC;
friend class WebGLExtensionCompressedTexturePVRTC;
friend class WebGLExtensionDepthTexture;
friend class WebGLExtensionDrawBuffers;
enum {
UNPACK_FLIP_Y_WEBGL = 0x9240,
@ -230,11 +231,13 @@ public:
const WebGLRectangleObject *FramebufferRectangleObject() const;
static const size_t sMaxColorAttachments = 16;
// This is similar to GLContext::ClearSafely, but tries to minimize the
// amount of work it does.
// It only clears the buffers we specify, and can reset its state without
// first having to query anything, as WebGL knows its state at all times.
void ForceClearFramebufferWithDefaultValues(GLbitfield mask);
void ForceClearFramebufferWithDefaultValues(GLbitfield mask, const bool colorAttachmentsMask[sMaxColorAttachments]);
// Calls ForceClearFramebufferWithDefaultValues() for the Context's 'screen'.
void ClearScreen();
@ -831,6 +834,8 @@ protected:
int32_t mGLMaxVaryingVectors;
int32_t mGLMaxFragmentUniformVectors;
int32_t mGLMaxVertexUniformVectors;
int32_t mGLMaxColorAttachments;
int32_t mGLMaxDrawBuffers;
// Cache the max number of elements that can be read from bound VBOs
// (result of ValidateBuffers).
@ -875,6 +880,7 @@ protected:
WEBGL_debug_renderer_info,
WEBGL_depth_texture,
WEBGL_lose_context,
WEBGL_draw_buffers,
WebGLExtensionID_unknown_extension
};
nsTArray<nsRefPtr<WebGLExtensionBase> > mExtensions;
@ -918,7 +924,7 @@ protected:
void Invalidate();
void DestroyResourcesAndContext();
void MakeContextCurrent() { gl->MakeCurrent(); }
void MakeContextCurrent() const { gl->MakeCurrent(); }
// helpers
void TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum internalformat,

View File

@ -14,6 +14,7 @@
#include "WebGLRenderbuffer.h"
#include "WebGLShaderPrecisionFormat.h"
#include "WebGLTexture.h"
#include "WebGLExtensions.h"
#include "nsString.h"
#include "nsDebug.h"
@ -571,8 +572,31 @@ WebGLContext::CheckFramebufferStatus(WebGLenum target)
return LOCAL_GL_FRAMEBUFFER_COMPLETE;
if(mBoundFramebuffer->HasDepthStencilConflict())
return LOCAL_GL_FRAMEBUFFER_UNSUPPORTED;
if(!mBoundFramebuffer->ColorAttachment().IsDefined())
return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
bool hasImages = false;
hasImages |= mBoundFramebuffer->DepthAttachment().IsDefined();
hasImages |= mBoundFramebuffer->StencilAttachment().IsDefined();
hasImages |= mBoundFramebuffer->DepthStencilAttachment().IsDefined();
if (!hasImages) {
int32_t colorAttachmentCount = mBoundFramebuffer->mColorAttachments.Length();
for(int32_t i = 0; i < colorAttachmentCount; i++) {
if (mBoundFramebuffer->ColorAttachment(i).IsDefined()) {
hasImages = true;
break;
}
}
/* http://www.khronos.org/registry/gles/specs/2.0/es_full_spec_2.0.25.pdf section 4.4.5 (page 118)
GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
No images are attached to the framebuffer.
*/
if (!hasImages) {
return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
}
}
if(mBoundFramebuffer->HasIncompleteAttachment())
return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
if(mBoundFramebuffer->HasAttachmentsOfMismatchedDimensions())
@ -851,8 +875,8 @@ WebGLContext::CopyTexImage2D(WebGLenum target,
bool texFormatRequiresAlpha = internalformat == LOCAL_GL_RGBA ||
internalformat == LOCAL_GL_ALPHA ||
internalformat == LOCAL_GL_LUMINANCE_ALPHA;
bool fboFormatHasAlpha = mBoundFramebuffer ? mBoundFramebuffer->ColorAttachment().HasAlpha()
: bool(gl->GetPixelFormat().alpha > 0);
bool fboFormatHasAlpha = mBoundFramebuffer ? mBoundFramebuffer->ColorAttachment(0).HasAlpha()
: bool(gl->GetPixelFormat().alpha > 0);
if (texFormatRequiresAlpha && !fboFormatHasAlpha)
return ErrorInvalidOperation("copyTexImage2D: texture format requires an alpha channel "
"but the framebuffer doesn't have one");
@ -961,8 +985,8 @@ WebGLContext::CopyTexSubImage2D(WebGLenum target,
bool texFormatRequiresAlpha = format == LOCAL_GL_RGBA ||
format == LOCAL_GL_ALPHA ||
format == LOCAL_GL_LUMINANCE_ALPHA;
bool fboFormatHasAlpha = mBoundFramebuffer ? mBoundFramebuffer->ColorAttachment().HasAlpha()
: bool(gl->GetPixelFormat().alpha > 0);
bool fboFormatHasAlpha = mBoundFramebuffer ? mBoundFramebuffer->ColorAttachment(0).HasAlpha()
: bool(gl->GetPixelFormat().alpha > 0);
if (texFormatRequiresAlpha && !fboFormatHasAlpha)
return ErrorInvalidOperation("copyTexSubImage2D: texture format requires an alpha channel "
@ -1698,10 +1722,10 @@ WebGLContext::FramebufferTexture2D(WebGLenum target,
if (!IsContextStable())
return;
if (mBoundFramebuffer)
return mBoundFramebuffer->FramebufferTexture2D(target, attachment, textarget, tobj, level);
else
return ErrorInvalidOperation("framebufferTexture2D: cannot modify framebuffer 0");
if (!mBoundFramebuffer)
return ErrorInvalidOperation("framebufferRenderbuffer: cannot modify framebuffer 0");
return mBoundFramebuffer->FramebufferTexture2D(target, attachment, textarget, tobj, level);
}
void
@ -1962,7 +1986,37 @@ WebGLContext::GetParameter(JSContext* cx, WebGLenum pname, ErrorResult& rv)
break;
}
}
if (IsExtensionEnabled(WEBGL_draw_buffers))
{
if (pname == LOCAL_GL_MAX_COLOR_ATTACHMENTS)
{
return JS::Int32Value(mGLMaxColorAttachments);
}
else if (pname == LOCAL_GL_MAX_DRAW_BUFFERS)
{
return JS::Int32Value(mGLMaxDrawBuffers);
}
else if (pname >= LOCAL_GL_DRAW_BUFFER0 &&
pname < WebGLenum(LOCAL_GL_DRAW_BUFFER0 + mGLMaxDrawBuffers))
{
if (mBoundFramebuffer) {
GLint iv = 0;
gl->fGetIntegerv(pname, &iv);
return JS::Int32Value(iv);
}
GLint iv = 0;
gl->fGetIntegerv(pname, &iv);
if (iv == GLint(LOCAL_GL_COLOR_ATTACHMENT0 + pname - LOCAL_GL_DRAW_BUFFER0)) {
return JS::Int32Value(LOCAL_GL_BACK);
}
return JS::Int32Value(LOCAL_GL_NONE);
}
}
switch (pname) {
//
// String params
@ -2309,15 +2363,26 @@ WebGLContext::GetFramebufferAttachmentParameter(JSContext* cx,
return JS::NullValue();
}
switch (attachment) {
case LOCAL_GL_COLOR_ATTACHMENT0:
case LOCAL_GL_DEPTH_ATTACHMENT:
case LOCAL_GL_STENCIL_ATTACHMENT:
case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
break;
default:
if (attachment != LOCAL_GL_DEPTH_ATTACHMENT &&
attachment != LOCAL_GL_STENCIL_ATTACHMENT &&
attachment != LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
{
if (IsExtensionEnabled(WEBGL_draw_buffers))
{
if (attachment < LOCAL_GL_COLOR_ATTACHMENT0 ||
attachment >= WebGLenum(LOCAL_GL_COLOR_ATTACHMENT0 + mGLMaxColorAttachments))
{
ErrorInvalidEnumInfo("getFramebufferAttachmentParameter: attachment", attachment);
return JS::NullValue();
}
mBoundFramebuffer->EnsureColorAttachments(attachment - LOCAL_GL_COLOR_ATTACHMENT0);
}
else if (attachment != LOCAL_GL_COLOR_ATTACHMENT0)
{
ErrorInvalidEnumInfo("getFramebufferAttachmentParameter: attachment", attachment);
return JS::NullValue();
}
}
if (!mBoundFramebuffer) {
@ -3402,7 +3467,7 @@ WebGLContext::ReadPixels(WebGLint x, WebGLint y, WebGLsizei width,
{
bool needAlphaFixup;
if (mBoundFramebuffer) {
needAlphaFixup = !mBoundFramebuffer->ColorAttachment().HasAlpha();
needAlphaFixup = !mBoundFramebuffer->ColorAttachment(0).HasAlpha();
} else {
needAlphaFixup = gl->GetPixelFormat().alpha == 0;
}
@ -4291,11 +4356,14 @@ WebGLContext::CompileShader(WebGLShader *shader)
resources.MaxCombinedTextureImageUnits = mGLMaxTextureUnits;
resources.MaxTextureImageUnits = mGLMaxTextureImageUnits;
resources.MaxFragmentUniformVectors = mGLMaxFragmentUniformVectors;
resources.MaxDrawBuffers = 1;
resources.MaxDrawBuffers = mGLMaxDrawBuffers;
if (IsExtensionEnabled(OES_standard_derivatives))
resources.OES_standard_derivatives = 1;
if (IsExtensionEnabled(WEBGL_draw_buffers))
resources.EXT_draw_buffers = 1;
// Tell ANGLE to allow highp in frag shaders. (unless disabled)
// If underlying GLES doesn't have highp in frag shaders, it should complain anyways.
resources.FragmentPrecisionHigh = mDisableFragHighP ? 0 : 1;
@ -5459,22 +5527,30 @@ WebGLContext::ReattachTextureToAnyFramebufferToWorkAroundBugs(WebGLTexture *tex,
framebuffer;
framebuffer = framebuffer->getNext())
{
if (framebuffer->ColorAttachment().Texture() == tex) {
framebuffer->FramebufferTexture2D(
LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
tex->Target(), tex, level);
size_t colorAttachmentCount = framebuffer->mColorAttachments.Length();
for (size_t i = 0; i < colorAttachmentCount; i++)
{
if (framebuffer->ColorAttachment(i).Texture() == tex) {
gl::ScopedBindFramebuffer autoFB(gl, framebuffer->GLName());
framebuffer->FramebufferTexture2D(
LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0 + i,
tex->Target(), tex, level);
}
}
if (framebuffer->DepthAttachment().Texture() == tex) {
gl::ScopedBindFramebuffer autoFB(gl, framebuffer->GLName());
framebuffer->FramebufferTexture2D(
LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
tex->Target(), tex, level);
}
if (framebuffer->StencilAttachment().Texture() == tex) {
gl::ScopedBindFramebuffer autoFB(gl, framebuffer->GLName());
framebuffer->FramebufferTexture2D(
LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
tex->Target(), tex, level);
}
if (framebuffer->DepthStencilAttachment().Texture() == tex) {
gl::ScopedBindFramebuffer autoFB(gl, framebuffer->GLName());
framebuffer->FramebufferTexture2D(
LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_STENCIL_ATTACHMENT,
tex->Target(), tex, level);

View File

@ -0,0 +1,153 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGLContext.h"
#include "WebGLExtensions.h"
#include "mozilla/dom/WebGLRenderingContextBinding.h"
#include "WebGLTexture.h"
#include "WebGLRenderbuffer.h"
#include "WebGLFramebuffer.h"
#include <algorithm>
using namespace mozilla;
using namespace gl;
WebGLExtensionDrawBuffers::WebGLExtensionDrawBuffers(WebGLContext* context)
: WebGLExtensionBase(context)
{
GLint maxColorAttachments = 0;
GLint maxDrawBuffers = 0;
gl::GLContext* gl = context->GL();
context->MakeContextCurrent();
gl->fGetIntegerv(LOCAL_GL_MAX_COLOR_ATTACHMENTS, &maxColorAttachments);
gl->fGetIntegerv(LOCAL_GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
// WEBGL_draw_buffers specifications don't give a maximal value reachable by MAX_COLOR_ATTACHMENTS.
maxColorAttachments = std::min(maxColorAttachments, GLint(WebGLContext::sMaxColorAttachments));
if (context->MinCapabilityMode())
{
maxColorAttachments = std::min(maxColorAttachments, GLint(sMinColorAttachments));
}
// WEBGL_draw_buffers specifications request MAX_COLOR_ATTACHMENTS >= MAX_DRAW_BUFFERS.
maxDrawBuffers = std::min(maxDrawBuffers, GLint(maxColorAttachments));
context->mGLMaxColorAttachments = maxColorAttachments;
context->mGLMaxDrawBuffers = maxDrawBuffers;
}
WebGLExtensionDrawBuffers::~WebGLExtensionDrawBuffers()
{
}
void WebGLExtensionDrawBuffers::DrawBuffersWEBGL(const dom::Sequence<GLenum>& buffers)
{
const size_t buffersLength = buffers.Length();
if (buffersLength == 0) {
return mContext->ErrorInvalidValue("drawBuffersWEBGL: invalid <buffers> (buffers must not be empty)");
}
if (mContext->mBoundFramebuffer == 0)
{
// OK: we are rendering in the default framebuffer
/* EXT_draw_buffers :
If the GL is bound to the default framebuffer, then <buffersLength> must be 1
and the constant must be BACK or NONE. When draw buffer zero is
BACK, color values are written into the sole buffer for single-
buffered contexts, or into the back buffer for double-buffered
contexts. If DrawBuffersEXT is supplied with a constant other than
BACK and NONE, the error INVALID_OPERATION is generated.
*/
if (buffersLength != 1) {
return mContext->ErrorInvalidValue("drawBuffersWEBGL: invalid <buffers> (main framebuffer: buffers.length must be 1)");
}
mContext->MakeContextCurrent();
if (buffers[0] == LOCAL_GL_NONE) {
const GLenum drawBufffersCommand = LOCAL_GL_NONE;
mContext->GL()->fDrawBuffers(1, &drawBufffersCommand);
return;
}
else if (buffers[0] == LOCAL_GL_BACK) {
const GLenum drawBufffersCommand = LOCAL_GL_COLOR_ATTACHMENT0;
mContext->GL()->fDrawBuffers(1, &drawBufffersCommand);
return;
}
return mContext->ErrorInvalidOperation("drawBuffersWEBGL: invalid operation (main framebuffer: buffers[0] must be GL_NONE or GL_BACK)");
}
// OK: we are rendering in a framebuffer object
if (buffersLength > size_t(mContext->mGLMaxDrawBuffers)) {
/* EXT_draw_buffers :
The maximum number of draw buffers is implementation-dependent. The
number of draw buffers supported can be queried by calling
GetIntegerv with the symbolic constant MAX_DRAW_BUFFERS_EXT. An
INVALID_VALUE error is generated if <buffersLength> is greater than
MAX_DRAW_BUFFERS_EXT.
*/
return mContext->ErrorInvalidValue("drawBuffersWEBGL: invalid <buffers> (buffers.length > GL_MAX_DRAW_BUFFERS)");
}
for (uint32_t i = 0; i < buffersLength; i++)
{
/* EXT_draw_buffers :
If the GL is bound to a draw framebuffer object, the <i>th buffer listed
in <bufs> must be COLOR_ATTACHMENT<i>_EXT or NONE. Specifying a
buffer out of order, BACK, or COLOR_ATTACHMENT<m>_EXT where <m> is
greater than or equal to the value of MAX_COLOR_ATTACHMENTS_EXT,
will generate the error INVALID_OPERATION.
*/
/* WEBGL_draw_buffers :
The value of the MAX_COLOR_ATTACHMENTS_WEBGL parameter must be greater than or equal to that of the MAX_DRAW_BUFFERS_WEBGL parameter.
*/
if (buffers[i] != LOCAL_GL_NONE &&
buffers[i] != GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + i)) {
return mContext->ErrorInvalidOperation("drawBuffersWEBGL: invalid operation (buffers[i] must be GL_NONE or GL_COLOR_ATTACHMENTi)");
}
}
mContext->MakeContextCurrent();
mContext->GL()->fDrawBuffers(buffersLength, buffers.Elements());
}
bool WebGLExtensionDrawBuffers::IsSupported(const WebGLContext* context)
{
gl::GLContext * gl = context->GL();
if (!gl->IsExtensionSupported(gl->IsGLES2() ? GLContext::EXT_draw_buffers
: GLContext::ARB_draw_buffers)) {
return false;
}
GLint supportedColorAttachments = 0;
GLint supportedDrawBuffers = 0;
context->MakeContextCurrent();
gl->fGetIntegerv(LOCAL_GL_MAX_COLOR_ATTACHMENTS, &supportedColorAttachments);
gl->fGetIntegerv(LOCAL_GL_MAX_COLOR_ATTACHMENTS, &supportedDrawBuffers);
if (size_t(supportedColorAttachments) < sMinColorAttachments){
// WEBGL_draw_buffers specifications request for 4 color attachments at least.
return false;
}
if (size_t(supportedDrawBuffers) < sMinDrawBuffers){
return false;
}
return true;
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDrawBuffers)

View File

@ -150,6 +150,28 @@ public:
DECL_WEBGL_EXTENSION_GOOP
};
class WebGLExtensionDrawBuffers
: public WebGLExtensionBase
{
public:
WebGLExtensionDrawBuffers(WebGLContext*);
virtual ~WebGLExtensionDrawBuffers();
void DrawBuffersWEBGL(const dom::Sequence<GLenum>& buffers);
static bool IsSupported(const WebGLContext*);
static const size_t sMinColorAttachments = 4;
static const size_t sMinDrawBuffers = 4;
/*
WEBGL_draw_buffers does not give a minal value for GL_MAX_DRAW_BUFFERS. But, we request
for GL_MAX_DRAW_BUFFERS = 4 at least to be able to use all requested color attachements.
See DrawBuffersWEBGL in WebGLExtensionDrawBuffers.cpp inner comments for more informations.
*/
DECL_WEBGL_EXTENSION_GOOP
};
} // namespace mozilla
#endif // WEBGLEXTENSIONS_H_

View File

@ -5,10 +5,13 @@
#include "WebGLContext.h"
#include "WebGLFramebuffer.h"
#include "WebGLExtensions.h"
#include "WebGLRenderbuffer.h"
#include "WebGLTexture.h"
#include "mozilla/dom/WebGLRenderingContextBinding.h"
#include "nsContentUtils.h"
#include "WebGLTexture.h"
#include "WebGLRenderbuffer.h"
using namespace mozilla;
@ -20,7 +23,6 @@ WebGLFramebuffer::WrapObject(JSContext *cx, JS::Handle<JSObject*> scope) {
WebGLFramebuffer::WebGLFramebuffer(WebGLContext *context)
: WebGLContextBoundObject(context)
, mHasEverBeenBound(false)
, mColorAttachment(LOCAL_GL_COLOR_ATTACHMENT0)
, mDepthAttachment(LOCAL_GL_DEPTH_ATTACHMENT)
, mStencilAttachment(LOCAL_GL_STENCIL_ATTACHMENT)
, mDepthStencilAttachment(LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
@ -29,6 +31,9 @@ WebGLFramebuffer::WebGLFramebuffer(WebGLContext *context)
mContext->MakeContextCurrent();
mContext->gl->fGenFramebuffers(1, &mGLName);
mContext->mFramebuffers.insertBack(this);
mColorAttachments.SetLength(1);
mColorAttachments[0].mAttachmentPoint = LOCAL_GL_COLOR_ATTACHMENT0;
}
bool
@ -98,40 +103,43 @@ WebGLFramebuffer::Attachment::IsComplete() const {
return false;
WebGLenum format = mTexturePtr->ImageInfoAt(0).Format();
switch (mAttachmentPoint)
{
case LOCAL_GL_COLOR_ATTACHMENT0:
return format == LOCAL_GL_ALPHA ||
format == LOCAL_GL_LUMINANCE ||
format == LOCAL_GL_LUMINANCE_ALPHA ||
format == LOCAL_GL_RGB ||
format == LOCAL_GL_RGBA;
case LOCAL_GL_DEPTH_ATTACHMENT:
return format == LOCAL_GL_DEPTH_COMPONENT;
case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
return format == LOCAL_GL_DEPTH_STENCIL;
default:
MOZ_NOT_REACHED("Invalid WebGL texture format?");
if (mAttachmentPoint == LOCAL_GL_DEPTH_ATTACHMENT) {
return format == LOCAL_GL_DEPTH_COMPONENT;
}
else if (mAttachmentPoint == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
return format == LOCAL_GL_DEPTH_STENCIL;
}
else if (mAttachmentPoint >= LOCAL_GL_COLOR_ATTACHMENT0 &&
mAttachmentPoint < WebGLenum(LOCAL_GL_COLOR_ATTACHMENT0 + WebGLContext::sMaxColorAttachments)) {
return (format == LOCAL_GL_ALPHA ||
format == LOCAL_GL_LUMINANCE ||
format == LOCAL_GL_LUMINANCE_ALPHA ||
format == LOCAL_GL_RGB ||
format == LOCAL_GL_RGBA);
}
MOZ_NOT_REACHED("Invalid WebGL attachment poin?");
}
if (mRenderbufferPtr) {
WebGLenum format = mRenderbufferPtr->InternalFormat();
switch (mAttachmentPoint) {
case LOCAL_GL_COLOR_ATTACHMENT0:
return format == LOCAL_GL_RGB565 ||
format == LOCAL_GL_RGB5_A1 ||
format == LOCAL_GL_RGBA4;
case LOCAL_GL_DEPTH_ATTACHMENT:
return format == LOCAL_GL_DEPTH_COMPONENT16;
case LOCAL_GL_STENCIL_ATTACHMENT:
return format == LOCAL_GL_STENCIL_INDEX8;
case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
return format == LOCAL_GL_DEPTH_STENCIL;
default:
NS_ABORT(); // should have been validated earlier
if (mAttachmentPoint == LOCAL_GL_DEPTH_ATTACHMENT) {
return format == LOCAL_GL_DEPTH_COMPONENT16;
}
else if (mAttachmentPoint == LOCAL_GL_STENCIL_ATTACHMENT) {
return format == LOCAL_GL_STENCIL_INDEX8;
}
else if (mAttachmentPoint == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
return format == LOCAL_GL_DEPTH_STENCIL;
}
else if (mAttachmentPoint >= LOCAL_GL_COLOR_ATTACHMENT0 &&
mAttachmentPoint < WebGLenum(LOCAL_GL_COLOR_ATTACHMENT0 + WebGLContext::sMaxColorAttachments)) {
return (format == LOCAL_GL_RGB565 ||
format == LOCAL_GL_RGB5_A1 ||
format == LOCAL_GL_RGBA4);
}
MOZ_NOT_REACHED("Invalid WebGL attachment poin?");
}
NS_ABORT(); // should never get there
@ -140,7 +148,7 @@ WebGLFramebuffer::Attachment::IsComplete() const {
void
WebGLFramebuffer::Delete() {
mColorAttachment.Reset();
mColorAttachments.Clear();
mDepthAttachment.Reset();
mStencilAttachment.Reset();
mDepthStencilAttachment.Reset();
@ -178,10 +186,13 @@ WebGLFramebuffer::FramebufferRenderbuffer(WebGLenum target,
break;
default:
// finish checking that the 'attachment' parameter is among the allowed values
if (attachment != LOCAL_GL_COLOR_ATTACHMENT0)
return mContext->ErrorInvalidEnumInfo("framebufferRenderbuffer: attachment", attachment);
if (!CheckColorAttachementNumber(attachment, "framebufferRenderbuffer")){
return;
}
mColorAttachment.SetRenderbuffer(wrb);
size_t colorAttachmentId = size_t(attachment - LOCAL_GL_COLOR_ATTACHMENT0);
EnsureColorAttachments(colorAttachmentId);
mColorAttachments[colorAttachmentId].SetRenderbuffer(wrb);
break;
}
@ -241,10 +252,13 @@ WebGLFramebuffer::FramebufferTexture2D(WebGLenum target,
mDepthStencilAttachment.SetTexture(wtex, level, face);
break;
default:
if (attachment != LOCAL_GL_COLOR_ATTACHMENT0)
return mContext->ErrorInvalidEnumInfo("framebufferTexture2D: attachment", attachment);
if (!CheckColorAttachementNumber(attachment, "framebufferTexture2D")){
return;
}
mColorAttachment.SetTexture(wtex, level, face);
size_t colorAttachmentId = size_t(attachment - LOCAL_GL_COLOR_ATTACHMENT0);
EnsureColorAttachments(colorAttachmentId);
mColorAttachments[colorAttachmentId].SetTexture(wtex, level, face);
break;
}
@ -270,6 +284,40 @@ WebGLFramebuffer::FramebufferTexture2D(WebGLenum target,
return;
}
bool
WebGLFramebuffer::HasIncompleteAttachment() const {
int32_t colorAttachmentCount = mColorAttachments.Length();
for (int32_t i = 0; i < colorAttachmentCount; i++)
{
if (mColorAttachments[i].IsDefined() && !mColorAttachments[i].IsComplete())
{
return true;
}
}
return ((mDepthAttachment.IsDefined() && !mDepthAttachment.IsComplete()) ||
(mStencilAttachment.IsDefined() && !mStencilAttachment.IsComplete()) ||
(mDepthStencilAttachment.IsDefined() && !mDepthStencilAttachment.IsComplete()));
}
bool
WebGLFramebuffer::HasAttachmentsOfMismatchedDimensions() const {
int32_t colorAttachmentCount = mColorAttachments.Length();
for (int32_t i = 1; i < colorAttachmentCount; i++)
{
if (mColorAttachments[i].IsDefined() && !mColorAttachments[i].HasSameDimensionsAs(mColorAttachments[0]))
{
return true;
}
}
return ((mDepthAttachment.IsDefined() && !mDepthAttachment.HasSameDimensionsAs(mColorAttachments[0])) ||
(mStencilAttachment.IsDefined() && !mStencilAttachment.HasSameDimensionsAs(mColorAttachments[0])) ||
(mDepthStencilAttachment.IsDefined() && !mDepthStencilAttachment.HasSameDimensionsAs(mColorAttachments[0])));
}
const WebGLFramebuffer::Attachment&
WebGLFramebuffer::GetAttachment(WebGLenum attachment) const {
if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
@ -279,14 +327,32 @@ WebGLFramebuffer::GetAttachment(WebGLenum attachment) const {
if (attachment == LOCAL_GL_STENCIL_ATTACHMENT)
return mStencilAttachment;
NS_ASSERTION(attachment == LOCAL_GL_COLOR_ATTACHMENT0, "bad attachment!");
return mColorAttachment;
if (!CheckColorAttachementNumber(attachment, "getAttachment")) {
NS_ABORT();
return mColorAttachments[0];
}
uint32_t colorAttachmentId = uint32_t(attachment - LOCAL_GL_COLOR_ATTACHMENT0);
if (colorAttachmentId >= mColorAttachments.Length()) {
NS_ABORT();
return mColorAttachments[0];
}
return mColorAttachments[colorAttachmentId];
}
void
WebGLFramebuffer::DetachTexture(const WebGLTexture *tex) {
if (mColorAttachment.Texture() == tex)
FramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, LOCAL_GL_TEXTURE_2D, nullptr, 0);
int32_t colorAttachmentCount = mColorAttachments.Length();
for (int32_t i = 0; i < colorAttachmentCount; i++) {
if (mColorAttachments[i].Texture() == tex) {
FramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, LOCAL_GL_TEXTURE_2D, nullptr, 0);
// a texture might be attached more that once while editing the framebuffer
}
}
if (mDepthAttachment.Texture() == tex)
FramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT, LOCAL_GL_TEXTURE_2D, nullptr, 0);
if (mStencilAttachment.Texture() == tex)
@ -297,8 +363,15 @@ WebGLFramebuffer::DetachTexture(const WebGLTexture *tex) {
void
WebGLFramebuffer::DetachRenderbuffer(const WebGLRenderbuffer *rb) {
if (mColorAttachment.Renderbuffer() == rb)
FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, LOCAL_GL_RENDERBUFFER, nullptr);
int32_t colorAttachmentCount = mColorAttachments.Length();
for (int32_t i = 0; i < colorAttachmentCount; i++) {
if (mColorAttachments[0].Renderbuffer() == rb) {
FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, LOCAL_GL_RENDERBUFFER, nullptr);
// a renderbuffer might be attached more that once while editing the framebuffer
}
}
if (mDepthAttachment.Renderbuffer() == rb)
FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT, LOCAL_GL_RENDERBUFFER, nullptr);
if (mStencilAttachment.Renderbuffer() == rb)
@ -318,14 +391,26 @@ WebGLFramebuffer::CheckAndInitializeRenderbuffers()
if (HasIncompleteAttachment())
return false;
if (!mColorAttachment.HasUninitializedRenderbuffer() &&
!mDepthAttachment.HasUninitializedRenderbuffer() &&
!mStencilAttachment.HasUninitializedRenderbuffer() &&
!mDepthStencilAttachment.HasUninitializedRenderbuffer())
return true;
size_t colorAttachmentCount = size_t(mColorAttachments.Length());
{
bool hasUnitializedRenderbuffers = false;
for (size_t i = 0; i < colorAttachmentCount; i++) {
hasUnitializedRenderbuffers |= mColorAttachments[i].HasUninitializedRenderbuffer();
}
if (!hasUnitializedRenderbuffers &&
!mDepthAttachment.HasUninitializedRenderbuffer() &&
!mStencilAttachment.HasUninitializedRenderbuffer() &&
!mDepthStencilAttachment.HasUninitializedRenderbuffer())
{
return true;
}
}
// ensure INVALID_FRAMEBUFFER_OPERATION in zero-size case
const WebGLRectangleObject *rect = mColorAttachment.RectangleObject();
const WebGLRectangleObject *rect = mColorAttachments[0].RectangleObject();
if (!rect ||
!rect->Width() ||
!rect->Height())
@ -338,9 +423,18 @@ WebGLFramebuffer::CheckAndInitializeRenderbuffers()
return false;
uint32_t mask = 0;
bool colorAttachmentsMask[WebGLContext::sMaxColorAttachments] = { false };
if (mColorAttachment.HasUninitializedRenderbuffer())
mask |= LOCAL_GL_COLOR_BUFFER_BIT;
MOZ_ASSERT( colorAttachmentCount <= WebGLContext::sMaxColorAttachments );
for (size_t i = 0; i < colorAttachmentCount; i++)
{
colorAttachmentsMask[i] = mColorAttachments[i].HasUninitializedRenderbuffer();
if (colorAttachmentsMask[i]) {
mask |= LOCAL_GL_COLOR_BUFFER_BIT;
}
}
if (mDepthAttachment.HasUninitializedRenderbuffer() ||
mDepthStencilAttachment.HasUninitializedRenderbuffer())
@ -354,10 +448,14 @@ WebGLFramebuffer::CheckAndInitializeRenderbuffers()
mask |= LOCAL_GL_STENCIL_BUFFER_BIT;
}
mContext->ForceClearFramebufferWithDefaultValues(mask);
mContext->ForceClearFramebufferWithDefaultValues(mask, colorAttachmentsMask);
if (mColorAttachment.HasUninitializedRenderbuffer())
mColorAttachment.Renderbuffer()->SetInitialized(true);
for (size_t i = 0; i < colorAttachmentCount; i++)
{
if (colorAttachmentsMask[i]) {
mColorAttachments[i].Renderbuffer()->SetInitialized(true);
}
}
if (mDepthAttachment.HasUninitializedRenderbuffer())
mDepthAttachment.Renderbuffer()->SetInitialized(true);
@ -371,9 +469,74 @@ WebGLFramebuffer::CheckAndInitializeRenderbuffers()
return true;
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_8(WebGLFramebuffer,
mColorAttachment.mTexturePtr,
mColorAttachment.mRenderbufferPtr,
bool WebGLFramebuffer::CheckColorAttachementNumber(WebGLenum attachment, const char * functionName) const
{
const char* const errorFormating = "%s: attachment: invalid enum value 0x%x";
if (mContext->IsExtensionEnabled(WebGLContext::WEBGL_draw_buffers))
{
if (attachment < LOCAL_GL_COLOR_ATTACHMENT0 ||
attachment > WebGLenum(LOCAL_GL_COLOR_ATTACHMENT0 + mContext->mGLMaxColorAttachments))
{
mContext->ErrorInvalidEnum(errorFormating, functionName, attachment);
return false;
}
}
else if (attachment != LOCAL_GL_COLOR_ATTACHMENT0)
{
if (attachment > LOCAL_GL_COLOR_ATTACHMENT0 &&
attachment <= LOCAL_GL_COLOR_ATTACHMENT15)
{
mContext->ErrorInvalidEnum("%s: attachment: invalid enum value 0x%x. "
"Try the WEBGL_draw_buffers extension if supported.", functionName, attachment);
return false;
}
else
{
mContext->ErrorInvalidEnum(errorFormating, functionName, attachment);
return false;
}
}
return true;
}
void WebGLFramebuffer::EnsureColorAttachments(size_t colorAttachmentId) {
size_t currentAttachmentCount = mColorAttachments.Length();
if (mColorAttachments.Length() > colorAttachmentId) {
return;
}
MOZ_ASSERT( colorAttachmentId < WebGLContext::sMaxColorAttachments );
mColorAttachments.SetLength(colorAttachmentId + 1);
for (size_t i = colorAttachmentId; i >= currentAttachmentCount; i--) {
mColorAttachments[i].mAttachmentPoint = LOCAL_GL_COLOR_ATTACHMENT0 + i;
}
}
inline void
ImplCycleCollectionUnlink(mozilla::WebGLFramebuffer::Attachment& aField)
{
aField.mTexturePtr = nullptr;
aField.mRenderbufferPtr = nullptr;
}
inline void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
mozilla::WebGLFramebuffer::Attachment& aField,
const char* aName,
uint32_t aFlags = 0)
{
CycleCollectionNoteEdgeName(aCallback, aName, aFlags);
aCallback.NoteXPCOMChild(aField.mTexturePtr);
aCallback.NoteXPCOMChild(aField.mRenderbufferPtr);
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_7(WebGLFramebuffer,
mColorAttachments,
mDepthAttachment.mTexturePtr,
mDepthAttachment.mRenderbufferPtr,
mStencilAttachment.mTexturePtr,

View File

@ -31,7 +31,7 @@ public:
DeleteOnce();
}
class Attachment
struct Attachment
{
// deleting a texture or renderbuffer immediately detaches it
WebGLRefPtr<WebGLTexture> mTexturePtr;
@ -40,10 +40,7 @@ public:
WebGLint mTextureLevel;
WebGLenum mTextureCubeMapFace;
friend class WebGLFramebuffer;
public:
Attachment(WebGLenum aAttachmentPoint)
Attachment(WebGLenum aAttachmentPoint = LOCAL_GL_COLOR_ATTACHMENT0)
: mAttachmentPoint(aAttachmentPoint)
{}
@ -109,12 +106,7 @@ public:
WebGLTexture *wtex,
WebGLint level);
bool HasIncompleteAttachment() const {
return (mColorAttachment.IsDefined() && !mColorAttachment.IsComplete()) ||
(mDepthAttachment.IsDefined() && !mDepthAttachment.IsComplete()) ||
(mStencilAttachment.IsDefined() && !mStencilAttachment.IsComplete()) ||
(mDepthStencilAttachment.IsDefined() && !mDepthStencilAttachment.IsComplete());
}
bool HasIncompleteAttachment() const;
bool HasDepthStencilConflict() const {
return int(mDepthAttachment.IsDefined()) +
@ -122,14 +114,10 @@ public:
int(mDepthStencilAttachment.IsDefined()) >= 2;
}
bool HasAttachmentsOfMismatchedDimensions() const {
return (mDepthAttachment.IsDefined() && !mDepthAttachment.HasSameDimensionsAs(mColorAttachment)) ||
(mStencilAttachment.IsDefined() && !mStencilAttachment.HasSameDimensionsAs(mColorAttachment)) ||
(mDepthStencilAttachment.IsDefined() && !mDepthStencilAttachment.HasSameDimensionsAs(mColorAttachment));
}
bool HasAttachmentsOfMismatchedDimensions() const;
const Attachment& ColorAttachment() const {
return mColorAttachment;
const Attachment& ColorAttachment(uint32_t colorAttachmentId) const {
return mColorAttachments[colorAttachmentId];
}
const Attachment& DepthAttachment() const {
@ -151,7 +139,7 @@ public:
void DetachRenderbuffer(const WebGLRenderbuffer *rb);
const WebGLRectangleObject *RectangleObject() {
return mColorAttachment.RectangleObject();
return mColorAttachments[0].RectangleObject();
}
WebGLContext *GetParentObject() const {
@ -166,13 +154,17 @@ public:
bool CheckAndInitializeRenderbuffers();
bool CheckColorAttachementNumber(WebGLenum attachment, const char * functionName) const;
WebGLuint mGLName;
bool mHasEverBeenBound;
void EnsureColorAttachments(size_t colorAttachmentId);
// we only store pointers to attached renderbuffers, not to attached textures, because
// we will only need to initialize renderbuffers. Textures are already initialized.
Attachment mColorAttachment,
mDepthAttachment,
nsTArray<Attachment> mColorAttachments;
Attachment mDepthAttachment,
mStencilAttachment,
mDepthStencilAttachment;
};

View File

@ -40,6 +40,7 @@ if CONFIG['MOZ_WEBGL']:
'WebGLExtensionCompressedTextureS3TC.cpp',
'WebGLExtensionDebugRendererInfo.cpp',
'WebGLExtensionDepthTexture.cpp',
'WebGLExtensionDrawBuffers.cpp',
'WebGLExtensionElementIndexUint.cpp',
'WebGLExtensionLoseContext.cpp',
'WebGLExtensionStandardDerivatives.cpp',

View File

@ -1192,6 +1192,11 @@ DOMInterfaces = {
'headerFile': 'WebGLExtensions.h'
},
'WebGLExtensionDrawBuffers': {
'nativeType': 'mozilla::WebGLExtensionDrawBuffers',
'headerFile': 'WebGLExtensions.h'
},
'WebGLFramebuffer': {
'nativeType': 'mozilla::WebGLFramebuffer',
'headerFile': 'WebGLFramebuffer.h'

View File

@ -837,6 +837,48 @@ interface WebGLExtensionTextureFloat
{
};
[NoInterfaceObject]
interface WebGLExtensionDrawBuffers {
const GLenum COLOR_ATTACHMENT0_WEBGL = 0x8CE0;
const GLenum COLOR_ATTACHMENT1_WEBGL = 0x8CE1;
const GLenum COLOR_ATTACHMENT2_WEBGL = 0x8CE2;
const GLenum COLOR_ATTACHMENT3_WEBGL = 0x8CE3;
const GLenum COLOR_ATTACHMENT4_WEBGL = 0x8CE4;
const GLenum COLOR_ATTACHMENT5_WEBGL = 0x8CE5;
const GLenum COLOR_ATTACHMENT6_WEBGL = 0x8CE6;
const GLenum COLOR_ATTACHMENT7_WEBGL = 0x8CE7;
const GLenum COLOR_ATTACHMENT8_WEBGL = 0x8CE8;
const GLenum COLOR_ATTACHMENT9_WEBGL = 0x8CE9;
const GLenum COLOR_ATTACHMENT10_WEBGL = 0x8CEA;
const GLenum COLOR_ATTACHMENT11_WEBGL = 0x8CEB;
const GLenum COLOR_ATTACHMENT12_WEBGL = 0x8CEC;
const GLenum COLOR_ATTACHMENT13_WEBGL = 0x8CED;
const GLenum COLOR_ATTACHMENT14_WEBGL = 0x8CEE;
const GLenum COLOR_ATTACHMENT15_WEBGL = 0x8CEF;
const GLenum DRAW_BUFFER0_WEBGL = 0x8825;
const GLenum DRAW_BUFFER1_WEBGL = 0x8826;
const GLenum DRAW_BUFFER2_WEBGL = 0x8827;
const GLenum DRAW_BUFFER3_WEBGL = 0x8828;
const GLenum DRAW_BUFFER4_WEBGL = 0x8829;
const GLenum DRAW_BUFFER5_WEBGL = 0x882A;
const GLenum DRAW_BUFFER6_WEBGL = 0x882B;
const GLenum DRAW_BUFFER7_WEBGL = 0x882C;
const GLenum DRAW_BUFFER8_WEBGL = 0x882D;
const GLenum DRAW_BUFFER9_WEBGL = 0x882E;
const GLenum DRAW_BUFFER10_WEBGL = 0x882F;
const GLenum DRAW_BUFFER11_WEBGL = 0x8830;
const GLenum DRAW_BUFFER12_WEBGL = 0x8831;
const GLenum DRAW_BUFFER13_WEBGL = 0x8832;
const GLenum DRAW_BUFFER14_WEBGL = 0x8833;
const GLenum DRAW_BUFFER15_WEBGL = 0x8834;
const GLenum MAX_COLOR_ATTACHMENTS_WEBGL = 0x8CDF;
const GLenum MAX_DRAW_BUFFERS_WEBGL = 0x8824;
void drawBuffersWEBGL(sequence<GLenum> buffers);
};
[NoInterfaceObject]
interface WebGLExtensionTextureFloatLinear
{

View File

@ -88,6 +88,8 @@ static const char *sExtensionNames[] = {
"GL_OES_element_index_uint",
"GL_OES_vertex_array_object",
"GL_ARB_vertex_array_object",
"GL_ARB_draw_buffers",
"GL_EXT_draw_buffers",
nullptr
};

View File

@ -1026,6 +1026,8 @@ public:
OES_element_index_uint,
OES_vertex_array_object,
ARB_vertex_array_object,
ARB_draw_buffers,
EXT_draw_buffers,
Extensions_Max
};
@ -1813,7 +1815,7 @@ public:
AFTER_GL_CALL;
}
void fDrawBuffers(GLsizei n, GLenum* bufs) {
void fDrawBuffers(GLsizei n, const GLenum* bufs) {
BEFORE_GL_CALL;
mSymbols.fDrawBuffers(n, bufs);
AFTER_GL_CALL;

View File

@ -3983,6 +3983,7 @@ pref("webgl.force-layers-readback", false);
pref("webgl.lose-context-on-heap-minimize", false);
pref("webgl.can-lose-context-in-foreground", true);
pref("webgl.max-warnings-per-context", 32);
pref("webgl.enable-draft-extensions", false);
#ifdef MOZ_WIDGET_GONK
pref("gfx.gralloc.fence-with-readpixels", false);
#endif