Bug 1522018 - Implement webgl draft ext EXT_float_blend. r=lsalzman,qdot
authorJeff Gilbert <jgilbert@mozilla.com>
Thu, 31 Jan 2019 23:39:12 +0000
changeset 456331 d324c3cd63b3ec8a0c6c27ea672c066080f82725
parent 456330 0720b49574804d0811e0bde2a387e1ccf28b9fce
child 456332 945770882765f6a4d2dd833a672c07a5a7b9bad7
push id35478
push usershindli@mozilla.com
push dateFri, 01 Feb 2019 03:55:46 +0000
treeherdermozilla-central@945770882765 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslsalzman, qdot
bugs1522018
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1522018 - Implement webgl draft ext EXT_float_blend. r=lsalzman,qdot Differential Revision: https://phabricator.services.mozilla.com/D17336
dom/bindings/Bindings.conf
dom/canvas/WebGLContext.h
dom/canvas/WebGLContextDraw.cpp
dom/canvas/WebGLContextExtensions.cpp
dom/canvas/WebGLContextState.cpp
dom/canvas/WebGLExtensionBase.cpp
dom/canvas/WebGLExtensions.cpp
dom/canvas/WebGLExtensions.h
dom/canvas/WebGLFramebuffer.cpp
dom/canvas/WebGLFramebuffer.h
dom/canvas/WebGLTypes.h
dom/canvas/moz.build
dom/webidl/WebGLRenderingContext.webidl
gfx/gl/GLContext.cpp
gfx/gl/GLContext.h
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1099,16 +1099,21 @@ DOMInterfaces = {
     'headerFile': 'WebGLActiveInfo.h'
 },
 
 'WebGLBuffer': {
     'nativeType': 'mozilla::WebGLBuffer',
     'headerFile': 'WebGLBuffer.h'
 },
 
+'EXT_float_blend': {
+    'nativeType': 'mozilla::WebGLExtensionFloatBlend',
+    'headerFile': 'WebGLExtensions.h'
+},
+
 'EXT_texture_compression_bptc': {
     'nativeType': 'mozilla::WebGLExtensionCompressedTextureBPTC',
     'headerFile': 'WebGLExtensions.h'
 },
 
 'EXT_texture_compression_rgtc': {
     'nativeType': 'mozilla::WebGLExtensionCompressedTextureRGTC',
     'headerFile': 'WebGLExtensions.h'
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -1042,16 +1042,17 @@ class WebGLContext : public nsICanvasRen
 
  private:
   // State tracking slots
   realGLboolean mDitherEnabled;
   realGLboolean mRasterizerDiscardEnabled;
   realGLboolean mScissorTestEnabled;
   realGLboolean mDepthTestEnabled = 0;
   realGLboolean mStencilTestEnabled;
+  realGLboolean mBlendEnabled = 0;
   GLenum mGenerateMipmapHint = 0;
 
   struct ScissorRect final {
     GLint x;
     GLint y;
     GLsizei w;
     GLsizei h;
 
--- a/dom/canvas/WebGLContextDraw.cpp
+++ b/dom/canvas/WebGLContextDraw.cpp
@@ -210,16 +210,27 @@ static bool DoSetsIntersect(const std::s
   return bool(intersection.size());
 }
 
 const webgl::CachedDrawFetchLimits* ValidateDraw(WebGLContext* const webgl,
                                                  const GLenum mode,
                                                  const uint32_t instanceCount) {
   if (!webgl->BindCurFBForDraw()) return nullptr;
 
+  const auto& fb = webgl->mBoundDrawFramebuffer;
+  if (fb && !webgl->IsExtensionEnabled(WebGLExtensionID::EXT_float_blend) &&
+      webgl->mBlendEnabled) {
+    const auto& info = *fb->GetCompletenessInfo();
+    if (info.hasFloat32) {
+      webgl->ErrorInvalidOperation(
+          "Float32 blending requires EXT_float_blend.");
+      return nullptr;
+    }
+  }
+
   switch (mode) {
     case LOCAL_GL_TRIANGLES:
     case LOCAL_GL_TRIANGLE_STRIP:
     case LOCAL_GL_TRIANGLE_FAN:
     case LOCAL_GL_POINTS:
     case LOCAL_GL_LINE_STRIP:
     case LOCAL_GL_LINE_LOOP:
     case LOCAL_GL_LINES:
--- a/dom/canvas/WebGLContextExtensions.cpp
+++ b/dom/canvas/WebGLContextExtensions.cpp
@@ -29,23 +29,24 @@ namespace mozilla {
 
 #define WEBGL_EXTENSION_IDENTIFIER(x) \
   sExtensionNamesEnumeratedArray[WebGLExtensionID::x] = #x;
 
     WEBGL_EXTENSION_IDENTIFIER(ANGLE_instanced_arrays)
     WEBGL_EXTENSION_IDENTIFIER(EXT_blend_minmax)
     WEBGL_EXTENSION_IDENTIFIER(EXT_color_buffer_float)
     WEBGL_EXTENSION_IDENTIFIER(EXT_color_buffer_half_float)
+    WEBGL_EXTENSION_IDENTIFIER(EXT_disjoint_timer_query)
+    WEBGL_EXTENSION_IDENTIFIER(EXT_float_blend)
     WEBGL_EXTENSION_IDENTIFIER(EXT_frag_depth)
     WEBGL_EXTENSION_IDENTIFIER(EXT_shader_texture_lod)
     WEBGL_EXTENSION_IDENTIFIER(EXT_sRGB)
     WEBGL_EXTENSION_IDENTIFIER(EXT_texture_compression_bptc)
     WEBGL_EXTENSION_IDENTIFIER(EXT_texture_compression_rgtc)
     WEBGL_EXTENSION_IDENTIFIER(EXT_texture_filter_anisotropic)
-    WEBGL_EXTENSION_IDENTIFIER(EXT_disjoint_timer_query)
     WEBGL_EXTENSION_IDENTIFIER(MOZ_debug)
     WEBGL_EXTENSION_IDENTIFIER(OES_element_index_uint)
     WEBGL_EXTENSION_IDENTIFIER(OES_standard_derivatives)
     WEBGL_EXTENSION_IDENTIFIER(OES_texture_float)
     WEBGL_EXTENSION_IDENTIFIER(OES_texture_float_linear)
     WEBGL_EXTENSION_IDENTIFIER(OES_texture_half_float)
     WEBGL_EXTENSION_IDENTIFIER(OES_texture_half_float_linear)
     WEBGL_EXTENSION_IDENTIFIER(OES_vertex_array_object)
@@ -213,25 +214,25 @@ bool WebGLContext::IsExtensionSupported(
         return gl->IsSupported(gl::GLFeature::depth_texture) ||
                gl->IsExtensionSupported(gl::GLContext::ANGLE_depth_texture);
       case WebGLExtensionID::WEBGL_draw_buffers:
         return WebGLExtensionDrawBuffers::IsSupported(this);
       default:
         // For warnings-as-errors.
         break;
     }
+  }
 
-    if (gfxPrefs::WebGLDraftExtensionsEnabled()) {
-      /*
-      switch (ext) {
+  if (gfxPrefs::WebGLDraftExtensionsEnabled()) {
+    switch (ext) {
+      case WebGLExtensionID::EXT_float_blend:
+        return WebGLExtensionFloatBlend::IsSupported(this);
+
       default:
-          // For warnings-as-errors.
-          break;
-      }
-      */
+        break;
     }
   }
 
   return false;
 }
 
 static bool CompareWebGLExtensionName(const nsACString& name,
                                       const char* other) {
@@ -317,16 +318,19 @@ void WebGLContext::EnableExtension(WebGL
       obj = new WebGLExtensionEXTColorBufferFloat(this);
       break;
     case WebGLExtensionID::EXT_color_buffer_half_float:
       obj = new WebGLExtensionColorBufferHalfFloat(this);
       break;
     case WebGLExtensionID::EXT_disjoint_timer_query:
       obj = new WebGLExtensionDisjointTimerQuery(this);
       break;
+    case WebGLExtensionID::EXT_float_blend:
+      obj = new WebGLExtensionFloatBlend(this);
+      break;
     case WebGLExtensionID::EXT_frag_depth:
       obj = new WebGLExtensionFragDepth(this);
       break;
     case WebGLExtensionID::EXT_shader_texture_lod:
       obj = new WebGLExtensionShaderTextureLod(this);
       break;
     case WebGLExtensionID::EXT_sRGB:
       obj = new WebGLExtensionSRGB(this);
--- a/dom/canvas/WebGLContextState.cpp
+++ b/dom/canvas/WebGLContextState.cpp
@@ -635,14 +635,16 @@ realGLboolean* WebGLContext::GetStateTra
     case LOCAL_GL_DITHER:
       return &mDitherEnabled;
     case LOCAL_GL_RASTERIZER_DISCARD:
       return &mRasterizerDiscardEnabled;
     case LOCAL_GL_SCISSOR_TEST:
       return &mScissorTestEnabled;
     case LOCAL_GL_STENCIL_TEST:
       return &mStencilTestEnabled;
+    case LOCAL_GL_BLEND:
+      return &mBlendEnabled;
   }
 
   return nullptr;
 }
 
 }  // namespace mozilla
rename from dom/canvas/WebGLExtensionBase.cpp
rename to dom/canvas/WebGLExtensions.cpp
--- a/dom/canvas/WebGLExtensionBase.cpp
+++ b/dom/canvas/WebGLExtensions.cpp
@@ -1,15 +1,19 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 "WebGLExtensions.h"
 
+#include "GLContext.h"
+#include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "WebGLContext.h"
+
 namespace mozilla {
 
 WebGLExtensionBase::WebGLExtensionBase(WebGLContext* context)
     : WebGLContextBoundObject(context), mIsLost(false) {}
 
 WebGLExtensionBase::~WebGLExtensionBase() {}
 
 void WebGLExtensionBase::MarkLost() {
@@ -18,9 +22,29 @@ void WebGLExtensionBase::MarkLost() {
   OnMarkLost();
 }
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLExtensionBase)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLExtensionBase, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLExtensionBase, Release)
 
+// -
+
+WebGLExtensionFloatBlend::WebGLExtensionFloatBlend(WebGLContext* const webgl)
+    : WebGLExtensionBase(webgl) {
+  MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
+}
+
+WebGLExtensionFloatBlend::~WebGLExtensionFloatBlend() = default;
+
+bool WebGLExtensionFloatBlend::IsSupported(const WebGLContext* const webgl) {
+  if (!webgl->IsWebGL2()) return false;
+  if (!WebGLExtensionEXTColorBufferFloat::IsSupported(webgl)) return false;
+
+  const auto& gl = webgl->gl;
+  return !gl->IsGLES() || gl->IsANGLE() ||
+         gl->IsExtensionSupported(gl::GLContext::EXT_float_blend);
+}
+
+IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionFloatBlend, EXT_float_blend)
+
 }  // namespace mozilla
--- a/dom/canvas/WebGLExtensions.h
+++ b/dom/canvas/WebGLExtensions.h
@@ -178,16 +178,26 @@ class WebGLExtensionEXTColorBufferFloat 
   explicit WebGLExtensionEXTColorBufferFloat(WebGLContext*);
   virtual ~WebGLExtensionEXTColorBufferFloat() {}
 
   static bool IsSupported(const WebGLContext*);
 
   DECL_WEBGL_EXTENSION_GOOP
 };
 
+class WebGLExtensionFloatBlend : public WebGLExtensionBase {
+ public:
+  explicit WebGLExtensionFloatBlend(WebGLContext* webgl);
+  virtual ~WebGLExtensionFloatBlend();
+
+  static bool IsSupported(const WebGLContext*);
+
+  DECL_WEBGL_EXTENSION_GOOP
+};
+
 class WebGLExtensionFragDepth : public WebGLExtensionBase {
  public:
   explicit WebGLExtensionFragDepth(WebGLContext*);
   virtual ~WebGLExtensionFragDepth();
 
   static bool IsSupported(const WebGLContext* context);
 
   DECL_WEBGL_EXTENSION_GOOP
--- a/dom/canvas/WebGLFramebuffer.cpp
+++ b/dom/canvas/WebGLFramebuffer.cpp
@@ -953,31 +953,37 @@ FBStatus WebGLFramebuffer::CheckFramebuf
 
     ResolveAttachmentData();
 
     // Sweet, let's cache that.
     auto info = CompletenessInfo{*this, UINT32_MAX, UINT32_MAX};
     mCompletenessInfo.ResetInvalidators({});
     mCompletenessInfo.AddInvalidator(*this);
 
+    const auto fnIsFloat32 = [](const webgl::FormatInfo& info) {
+      if (info.componentType != webgl::ComponentType::Float) return false;
+      return info.r == 32;
+    };
+
     for (const auto& cur : mAttachments) {
       const auto& tex = cur->Texture();
       const auto& rb = cur->Renderbuffer();
       if (tex) {
         mCompletenessInfo.AddInvalidator(*tex);
         info.texAttachments.push_back(cur);
       } else if (rb) {
         mCompletenessInfo.AddInvalidator(*rb);
       } else {
         continue;
       }
       const auto& imageInfo = cur->GetImageInfo();
       MOZ_ASSERT(imageInfo);
       info.width = std::min(info.width, imageInfo->mWidth);
       info.height = std::min(info.height, imageInfo->mHeight);
+      info.hasFloat32 |= fnIsFloat32(*imageInfo->mFormat->format);
     }
     mCompletenessInfo = Some(std::move(info));
     return LOCAL_GL_FRAMEBUFFER_COMPLETE;
   } while (false);
 
   MOZ_ASSERT(ret != LOCAL_GL_FRAMEBUFFER_COMPLETE);
   mContext->GenerateWarning("Framebuffer not complete. (status: 0x%04x) %s",
                             ret.get(), statusInfo.BeginReading());
--- a/dom/canvas/WebGLFramebuffer.h
+++ b/dom/canvas/WebGLFramebuffer.h
@@ -161,16 +161,17 @@ class WebGLFramebuffer final : public ns
 
   ////
 
   struct CompletenessInfo final {
     const WebGLFramebuffer& fb;
 
     uint32_t width = 0;
     uint32_t height = 0;
+    bool hasFloat32 = false;
 
     // IsFeedback
     std::vector<const WebGLFBAttachPoint*> texAttachments;  // Non-null
 
     ~CompletenessInfo();
   };
   friend struct CompletenessInfo;
 
--- a/dom/canvas/WebGLTypes.h
+++ b/dom/canvas/WebGLTypes.h
@@ -96,23 +96,24 @@ enum class WebGLTexImageFunc : uint8_t {
 enum class WebGLTexDimensions : uint8_t { Tex2D, Tex3D };
 
 // Please keep extensions in alphabetic order.
 enum class WebGLExtensionID : uint8_t {
   ANGLE_instanced_arrays,
   EXT_blend_minmax,
   EXT_color_buffer_float,
   EXT_color_buffer_half_float,
+  EXT_disjoint_timer_query,
+  EXT_float_blend,
+  EXT_frag_depth,
+  EXT_shader_texture_lod,
+  EXT_sRGB,
   EXT_texture_compression_bptc,
   EXT_texture_compression_rgtc,
-  EXT_frag_depth,
-  EXT_sRGB,
-  EXT_shader_texture_lod,
   EXT_texture_filter_anisotropic,
-  EXT_disjoint_timer_query,
   MOZ_debug,
   OES_element_index_uint,
   OES_standard_derivatives,
   OES_texture_float,
   OES_texture_float_linear,
   OES_texture_half_float,
   OES_texture_half_float_linear,
   OES_vertex_array_object,
--- a/dom/canvas/moz.build
+++ b/dom/canvas/moz.build
@@ -114,17 +114,16 @@ UNIFIED_SOURCES += [
     'WebGLContextGL.cpp',
     'WebGLContextLossHandler.cpp',
     'WebGLContextState.cpp',
     'WebGLContextTextures.cpp',
     'WebGLContextUtils.cpp',
     'WebGLContextValidate.cpp',
     'WebGLContextVertexArray.cpp',
     'WebGLContextVertices.cpp',
-    'WebGLExtensionBase.cpp',
     'WebGLExtensionBlendMinMax.cpp',
     'WebGLExtensionColorBufferFloat.cpp',
     'WebGLExtensionColorBufferHalfFloat.cpp',
     'WebGLExtensionCompressedTextureASTC.cpp',
     'WebGLExtensionCompressedTextureBPTC.cpp',
     'WebGLExtensionCompressedTextureES3.cpp',
     'WebGLExtensionCompressedTextureETC1.cpp',
     'WebGLExtensionCompressedTexturePVRTC.cpp',
@@ -137,16 +136,17 @@ UNIFIED_SOURCES += [
     'WebGLExtensionDisjointTimerQuery.cpp',
     'WebGLExtensionDrawBuffers.cpp',
     'WebGLExtensionElementIndexUint.cpp',
     'WebGLExtensionEXTColorBufferFloat.cpp',
     'WebGLExtensionFragDepth.cpp',
     'WebGLExtensionInstancedArrays.cpp',
     'WebGLExtensionLoseContext.cpp',
     'WebGLExtensionMOZDebug.cpp',
+    'WebGLExtensions.cpp',
     'WebGLExtensionShaderTextureLod.cpp',
     'WebGLExtensionSRGB.cpp',
     'WebGLExtensionStandardDerivatives.cpp',
     'WebGLExtensionTextureFilterAnisotropic.cpp',
     'WebGLExtensionTextureFloat.cpp',
     'WebGLExtensionTextureFloatLinear.cpp',
     'WebGLExtensionTextureHalfFloat.cpp',
     'WebGLExtensionTextureHalfFloatLinear.cpp',
--- a/dom/webidl/WebGLRenderingContext.webidl
+++ b/dom/webidl/WebGLRenderingContext.webidl
@@ -1112,8 +1112,12 @@ interface MOZ_debug {
 
     const GLenum WSI_INFO   = 0x10000;
     const GLenum UNPACK_REQUIRE_FASTPATH = 0x10001;
     const GLenum DOES_INDEX_VALIDATION   = 0x10002;
 
     [Throws]
     any getParameter(GLenum pname);
 };
+
+[NoInterfaceObject]
+interface EXT_float_blend {
+}; // interface EXT_float_blend
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -130,16 +130,17 @@ static const char* const sExtensionNames
     "GL_EXT_color_buffer_float",
     "GL_EXT_color_buffer_half_float",
     "GL_EXT_copy_texture",
     "GL_EXT_disjoint_timer_query",
     "GL_EXT_draw_buffers",
     "GL_EXT_draw_buffers2",
     "GL_EXT_draw_instanced",
     "GL_EXT_draw_range_elements",
+    "GL_EXT_float_blend",
     "GL_EXT_frag_depth",
     "GL_EXT_framebuffer_blit",
     "GL_EXT_framebuffer_multisample",
     "GL_EXT_framebuffer_object",
     "GL_EXT_framebuffer_sRGB",
     "GL_EXT_gpu_shader4",
     "GL_EXT_map_buffer_range",
     "GL_EXT_multisampled_render_to_texture",
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -409,16 +409,17 @@ class GLContext : public GLLibraryLoader
     EXT_color_buffer_float,
     EXT_color_buffer_half_float,
     EXT_copy_texture,
     EXT_disjoint_timer_query,
     EXT_draw_buffers,
     EXT_draw_buffers2,
     EXT_draw_instanced,
     EXT_draw_range_elements,
+    EXT_float_blend,
     EXT_frag_depth,
     EXT_framebuffer_blit,
     EXT_framebuffer_multisample,
     EXT_framebuffer_object,
     EXT_framebuffer_sRGB,
     EXT_gpu_shader4,
     EXT_map_buffer_range,
     EXT_multisampled_render_to_texture,