summaryrefslogtreecommitdiffstats
path: root/dom/canvas/WebGL2ContextFramebuffers.cpp
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /dom/canvas/WebGL2ContextFramebuffers.cpp
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'dom/canvas/WebGL2ContextFramebuffers.cpp')
-rw-r--r--dom/canvas/WebGL2ContextFramebuffers.cpp339
1 files changed, 339 insertions, 0 deletions
diff --git a/dom/canvas/WebGL2ContextFramebuffers.cpp b/dom/canvas/WebGL2ContextFramebuffers.cpp
new file mode 100644
index 000000000..c22bb9190
--- /dev/null
+++ b/dom/canvas/WebGL2ContextFramebuffers.cpp
@@ -0,0 +1,339 @@
+/* -*- 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 "WebGL2Context.h"
+
+#include "GLContext.h"
+#include "GLScreenBuffer.h"
+#include "WebGLContextUtils.h"
+#include "WebGLFormats.h"
+#include "WebGLFramebuffer.h"
+
+namespace mozilla {
+
+void
+WebGL2Context::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ if (IsContextLost())
+ return;
+
+ const GLbitfield validBits = LOCAL_GL_COLOR_BUFFER_BIT |
+ LOCAL_GL_DEPTH_BUFFER_BIT |
+ LOCAL_GL_STENCIL_BUFFER_BIT;
+ if ((mask | validBits) != validBits) {
+ ErrorInvalidValue("blitFramebuffer: Invalid bit set in mask.");
+ return;
+ }
+
+ switch (filter) {
+ case LOCAL_GL_NEAREST:
+ case LOCAL_GL_LINEAR:
+ break;
+ default:
+ ErrorInvalidEnumInfo("blitFramebuffer: Bad `filter`:", filter);
+ return;
+ }
+
+ ////
+
+ const auto& readFB = mBoundReadFramebuffer;
+ if (readFB &&
+ !readFB->ValidateAndInitAttachments("blitFramebuffer's READ_FRAMEBUFFER"))
+ {
+ return;
+ }
+
+ const auto& drawFB = mBoundDrawFramebuffer;
+ if (drawFB &&
+ !drawFB->ValidateAndInitAttachments("blitFramebuffer's DRAW_FRAMEBUFFER"))
+ {
+ return;
+ }
+
+ ////
+
+ if (!mBoundReadFramebuffer) {
+ ClearBackbufferIfNeeded();
+ }
+
+ WebGLFramebuffer::BlitFramebuffer(this,
+ readFB, srcX0, srcY0, srcX1, srcY1,
+ drawFB, dstX0, dstY0, dstX1, dstY1,
+ mask, filter);
+}
+
+void
+WebGL2Context::FramebufferTextureLayer(GLenum target, GLenum attachment,
+ WebGLTexture* texture, GLint level, GLint layer)
+{
+ const char funcName[] = "framebufferTextureLayer";
+ if (IsContextLost())
+ return;
+
+ if (!ValidateFramebufferTarget(target, funcName))
+ return;
+
+ WebGLFramebuffer* fb;
+ switch (target) {
+ case LOCAL_GL_FRAMEBUFFER:
+ case LOCAL_GL_DRAW_FRAMEBUFFER:
+ fb = mBoundDrawFramebuffer;
+ break;
+
+ case LOCAL_GL_READ_FRAMEBUFFER:
+ fb = mBoundReadFramebuffer;
+ break;
+
+ default:
+ MOZ_CRASH("GFX: Bad target.");
+ }
+
+ if (!fb)
+ return ErrorInvalidOperation("%s: Cannot modify framebuffer 0.", funcName);
+
+ fb->FramebufferTextureLayer(funcName, attachment, texture, level, layer);
+}
+
+JS::Value
+WebGL2Context::GetFramebufferAttachmentParameter(JSContext* cx,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ ErrorResult& out_error)
+{
+ return WebGLContext::GetFramebufferAttachmentParameter(cx, target, attachment, pname,
+ out_error);
+}
+
+////
+
+static bool
+ValidateBackbufferAttachmentEnum(WebGLContext* webgl, const char* funcName,
+ GLenum attachment)
+{
+ switch (attachment) {
+ case LOCAL_GL_COLOR:
+ 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)
+{
+ switch (attachment) {
+ case LOCAL_GL_DEPTH_ATTACHMENT:
+ case LOCAL_GL_STENCIL_ATTACHMENT:
+ case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
+ return true;
+ }
+
+ if (attachment < LOCAL_GL_COLOR_ATTACHMENT0) {
+ webgl->ErrorInvalidEnum("%s: attachment: invalid enum value 0x%x.",
+ funcName, attachment);
+ return false;
+ }
+
+ if (attachment > webgl->LastColorAttachmentEnum()) {
+ // That these errors have different types is ridiculous.
+ webgl->ErrorInvalidOperation("%s: Too-large LOCAL_GL_COLOR_ATTACHMENTn.",
+ funcName);
+ return false;
+ }
+
+ return true;
+}
+
+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:
+ scopedVector->push_back(LOCAL_GL_DEPTH_ATTACHMENT);
+ break;
+
+ case LOCAL_GL_STENCIL:
+ scopedVector->push_back(LOCAL_GL_STENCIL_ATTACHMENT);
+ break;
+
+ default:
+ MOZ_CRASH();
+ }
+ }
+ *out_glNumAttachments = scopedVector->size();
+ *out_glAttachments = scopedVector->data();
+ }
+ }
+
+ ////
+
+ if (!fb) {
+ ClearBackbufferIfNeeded();
+
+ // Don't do more validation after these.
+ Invalidate();
+ mShouldPresent = true;
+ }
+
+ return true;
+}
+
+void
+WebGL2Context::InvalidateFramebuffer(GLenum target,
+ const dom::Sequence<GLenum>& attachments,
+ ErrorResult& rv)
+{
+ const char funcName[] = "invalidateSubFramebuffer";
+
+ std::vector<GLenum> scopedVector;
+ GLsizei glNumAttachments;
+ const GLenum* glAttachments;
+ if (!ValidateInvalidateFramebuffer(funcName, target, attachments, &rv, &scopedVector,
+ &glNumAttachments, &glAttachments))
+ {
+ return;
+ }
+
+ ////
+
+ // 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;
+ }
+
+ // Use clear instead?
+ // No-op for now.
+}
+
+void
+WebGL2Context::InvalidateSubFramebuffer(GLenum target, const dom::Sequence<GLenum>& attachments,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ ErrorResult& rv)
+{
+ const char funcName[] = "invalidateSubFramebuffer";
+
+ if (!ValidateNonNegative(funcName, "width", width) ||
+ !ValidateNonNegative(funcName, "height", height))
+ {
+ return;
+ }
+
+ std::vector<GLenum> scopedVector;
+ GLsizei glNumAttachments;
+ const GLenum* glAttachments;
+ if (!ValidateInvalidateFramebuffer(funcName, target, attachments, &rv, &scopedVector,
+ &glNumAttachments, &glAttachments))
+ {
+ return;
+ }
+
+ ////
+
+ // 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;
+ }
+
+ // Use clear instead?
+ // No-op for now.
+}
+
+void
+WebGL2Context::ReadBuffer(GLenum mode)
+{
+ const char funcName[] = "readBuffer";
+ if (IsContextLost())
+ return;
+
+ if (mBoundReadFramebuffer) {
+ mBoundReadFramebuffer->ReadBuffer(funcName, mode);
+ return;
+ }
+
+ // Operating on the default framebuffer.
+ if (mode != LOCAL_GL_NONE &&
+ mode != LOCAL_GL_BACK)
+ {
+ nsCString enumName;
+ EnumName(mode, &enumName);
+ ErrorInvalidOperation("%s: If READ_FRAMEBUFFER is null, `mode` must be BACK or"
+ " NONE. Was %s.",
+ funcName, enumName.BeginReading());
+ return;
+ }
+
+ gl->Screen()->SetReadBuffer(mode);
+}
+
+} // namespace mozilla