mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
bug 843667 - implement WEBGL_draw_buffers and add the user preference webgl.enable-draft-extensions - r=bjacob
This commit is contained in:
parent
6910532ccd
commit
69a846c1a8
@ -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"));
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
153
content/canvas/src/WebGLExtensionDrawBuffers.cpp
Normal file
153
content/canvas/src/WebGLExtensionDrawBuffers.cpp
Normal 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)
|
@ -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_
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -40,6 +40,7 @@ if CONFIG['MOZ_WEBGL']:
|
||||
'WebGLExtensionCompressedTextureS3TC.cpp',
|
||||
'WebGLExtensionDebugRendererInfo.cpp',
|
||||
'WebGLExtensionDepthTexture.cpp',
|
||||
'WebGLExtensionDrawBuffers.cpp',
|
||||
'WebGLExtensionElementIndexUint.cpp',
|
||||
'WebGLExtensionLoseContext.cpp',
|
||||
'WebGLExtensionStandardDerivatives.cpp',
|
||||
|
@ -1192,6 +1192,11 @@ DOMInterfaces = {
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionDrawBuffers': {
|
||||
'nativeType': 'mozilla::WebGLExtensionDrawBuffers',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLFramebuffer': {
|
||||
'nativeType': 'mozilla::WebGLFramebuffer',
|
||||
'headerFile': 'WebGLFramebuffer.h'
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user