summaryrefslogtreecommitdiffstats
path: root/dom/canvas/WebGLContextFramebufferOperations.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/canvas/WebGLContextFramebufferOperations.cpp')
-rw-r--r--dom/canvas/WebGLContextFramebufferOperations.cpp228
1 files changed, 228 insertions, 0 deletions
diff --git a/dom/canvas/WebGLContextFramebufferOperations.cpp b/dom/canvas/WebGLContextFramebufferOperations.cpp
new file mode 100644
index 000000000..8b797d8a8
--- /dev/null
+++ b/dom/canvas/WebGLContextFramebufferOperations.cpp
@@ -0,0 +1,228 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* 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 "WebGLTexture.h"
+#include "WebGLRenderbuffer.h"
+#include "WebGLFramebuffer.h"
+#include "GLContext.h"
+#include "GLScreenBuffer.h"
+
+namespace mozilla {
+
+void
+WebGLContext::Clear(GLbitfield mask)
+{
+ const char funcName[] = "clear";
+
+ if (IsContextLost())
+ return;
+
+ MakeContextCurrent();
+
+ uint32_t m = mask & (LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT | LOCAL_GL_STENCIL_BUFFER_BIT);
+ if (mask != m)
+ return ErrorInvalidValue("%s: invalid mask bits", funcName);
+
+ if (mask == 0) {
+ GenerateWarning("Calling gl.clear(0) has no effect.");
+ } else if (mRasterizerDiscardEnabled) {
+ GenerateWarning("Calling gl.clear() with RASTERIZER_DISCARD enabled has no effects.");
+ }
+
+ if (mBoundDrawFramebuffer) {
+ if (!mBoundDrawFramebuffer->ValidateAndInitAttachments(funcName))
+ return;
+
+ if (mask & LOCAL_GL_COLOR_BUFFER_BIT) {
+ for (const auto& cur : mBoundDrawFramebuffer->ColorDrawBuffers()) {
+ if (!cur->IsDefined())
+ continue;
+
+ switch (cur->Format()->format->componentType) {
+ case webgl::ComponentType::Float:
+ case webgl::ComponentType::NormInt:
+ case webgl::ComponentType::NormUInt:
+ break;
+
+ default:
+ ErrorInvalidOperation("%s: Color draw buffers must be floating-point"
+ " or fixed-point. (normalized (u)ints)",
+ funcName);
+ return;
+ }
+ }
+ }
+ }
+
+ ScopedDrawCallWrapper wrapper(*this);
+ gl->fClear(mask);
+}
+
+static GLfloat
+GLClampFloat(GLfloat val)
+{
+ if (val < 0.0)
+ return 0.0;
+
+ if (val > 1.0)
+ return 1.0;
+
+ return val;
+}
+
+void
+WebGLContext::ClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
+{
+ if (IsContextLost())
+ return;
+
+ MakeContextCurrent();
+
+ const bool supportsFloatColorBuffers = (IsExtensionEnabled(WebGLExtensionID::EXT_color_buffer_float) ||
+ IsExtensionEnabled(WebGLExtensionID::EXT_color_buffer_half_float) ||
+ IsExtensionEnabled(WebGLExtensionID::WEBGL_color_buffer_float));
+ if (!supportsFloatColorBuffers) {
+ r = GLClampFloat(r);
+ g = GLClampFloat(g);
+ b = GLClampFloat(b);
+ a = GLClampFloat(a);
+ }
+
+ gl->fClearColor(r, g, b, a);
+
+ mColorClearValue[0] = r;
+ mColorClearValue[1] = g;
+ mColorClearValue[2] = b;
+ mColorClearValue[3] = a;
+}
+
+void
+WebGLContext::ClearDepth(GLclampf v)
+{
+ if (IsContextLost())
+ return;
+
+ MakeContextCurrent();
+ mDepthClearValue = GLClampFloat(v);
+ gl->fClearDepth(mDepthClearValue);
+}
+
+void
+WebGLContext::ClearStencil(GLint v)
+{
+ if (IsContextLost())
+ return;
+
+ MakeContextCurrent();
+ mStencilClearValue = v;
+ gl->fClearStencil(v);
+}
+
+void
+WebGLContext::ColorMask(WebGLboolean r, WebGLboolean g, WebGLboolean b, WebGLboolean a)
+{
+ if (IsContextLost())
+ return;
+
+ MakeContextCurrent();
+ mColorWriteMask[0] = r;
+ mColorWriteMask[1] = g;
+ mColorWriteMask[2] = b;
+ mColorWriteMask[3] = a;
+ gl->fColorMask(r, g, b, a);
+}
+
+void
+WebGLContext::DepthMask(WebGLboolean b)
+{
+ if (IsContextLost())
+ return;
+
+ MakeContextCurrent();
+ mDepthWriteMask = b;
+ gl->fDepthMask(b);
+}
+
+void
+WebGLContext::DrawBuffers(const dom::Sequence<GLenum>& buffers)
+{
+ const char funcName[] = "drawBuffers";
+ if (IsContextLost())
+ return;
+
+ if (mBoundDrawFramebuffer) {
+ mBoundDrawFramebuffer->DrawBuffers(funcName, buffers);
+ return;
+ }
+
+ // GLES 3.0.4 p186:
+ // "If the GL is bound to the default framebuffer, then `n` must be 1 and the
+ // constant must be BACK or NONE. [...] If DrawBuffers is supplied with a
+ // constant other than BACK and NONE, or with a value of `n` other than 1, the
+ // error INVALID_OPERATION is generated."
+ if (buffers.Length() != 1) {
+ ErrorInvalidOperation("%s: For the default framebuffer, `buffers` must have a"
+ " length of 1.",
+ funcName);
+ return;
+ }
+
+ switch (buffers[0]) {
+ case LOCAL_GL_NONE:
+ case LOCAL_GL_BACK:
+ break;
+
+ default:
+ ErrorInvalidOperation("%s: For the default framebuffer, `buffers[0]` must be"
+ " BACK or NONE.",
+ funcName);
+ return;
+ }
+
+ mDefaultFB_DrawBuffer0 = buffers[0];
+ gl->Screen()->SetDrawBuffer(buffers[0]);
+}
+
+void
+WebGLContext::StencilMask(GLuint mask)
+{
+ if (IsContextLost())
+ return;
+
+ mStencilWriteMaskFront = mask;
+ mStencilWriteMaskBack = mask;
+
+ MakeContextCurrent();
+ gl->fStencilMask(mask);
+}
+
+void
+WebGLContext::StencilMaskSeparate(GLenum face, GLuint mask)
+{
+ if (IsContextLost())
+ return;
+
+ if (!ValidateFaceEnum(face, "stencilMaskSeparate: face"))
+ return;
+
+ switch (face) {
+ case LOCAL_GL_FRONT_AND_BACK:
+ mStencilWriteMaskFront = mask;
+ mStencilWriteMaskBack = mask;
+ break;
+ case LOCAL_GL_FRONT:
+ mStencilWriteMaskFront = mask;
+ break;
+ case LOCAL_GL_BACK:
+ mStencilWriteMaskBack = mask;
+ break;
+ }
+
+ MakeContextCurrent();
+ gl->fStencilMaskSeparate(face, mask);
+}
+
+} // namespace mozilla