Bug 1200864 - Skip DrawElements buffer validation when we have robust_buffer_access. - r=kamidphish
☠☠ backed out by 5cc421782909 ☠ ☠
authorJeff Gilbert <jgilbert@mozilla.com>
Wed, 02 Sep 2015 14:06:58 -0700
changeset 293226 71886d218c121ad55afdab457f728168630e086d
parent 293225 137ead96908ad9a0544c587092b4e4fa386a0fee
child 293227 f0a54b1e9b60dbebc13d91967a402067271b0946
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskamidphish
bugs1200864
milestone43.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 1200864 - Skip DrawElements buffer validation when we have robust_buffer_access. - r=kamidphish
dom/canvas/WebGLContextDraw.cpp
gfx/gl/GLContext.cpp
gfx/gl/GLContext.h
gfx/gl/GLContextEGL.h
gfx/gl/GLContextFeatures.cpp
gfx/gl/GLContextProviderEGL.cpp
gfx/gl/GLDefs.h
--- a/dom/canvas/WebGLContextDraw.cpp
+++ b/dom/canvas/WebGLContextDraw.cpp
@@ -249,23 +249,28 @@ WebGLContext::DrawElements_check(GLsizei
     if (uint32_t(checked_neededByteCount.value()) > elemArrayBuffer.ByteLength()) {
         ErrorInvalidOperation("%s: bound element array buffer is too small for given count and offset", info);
         return false;
     }
 
     if (!ValidateBufferFetching(info))
         return false;
 
-    if (!mMaxFetchedVertices ||
-        !elemArrayBuffer.Validate(type, mMaxFetchedVertices - 1, first, count, out_upperBound))
-    {
-        ErrorInvalidOperation(
-                              "%s: bound vertex attribute buffers do not have sufficient "
-                              "size for given indices from the bound element array", info);
-        return false;
+    if (gl->IsSupported(GLFeature::robust_buffer_access_behavior)) {
+        *out_upperBound = 0;
+    } else {
+        if (!mMaxFetchedVertices ||
+            !elemArrayBuffer.Validate(type, mMaxFetchedVertices - 1, first, count,
+                                      out_upperBound))
+        {
+            ErrorInvalidOperation(
+                                  "%s: bound vertex attribute buffers do not have sufficient "
+                                  "size for given indices from the bound element array", info);
+            return false;
+        }
     }
 
     if (uint32_t(primcount) > mMaxFetchedInstances) {
         ErrorInvalidOperation("%s: bound instance attribute buffers do not have sufficient size for given primcount", info);
         return false;
     }
 
     // Bug 1008310 - Check if buffer has been used with a different previous type
@@ -317,17 +322,17 @@ WebGLContext::DrawElements(GLenum mode, 
         return;
     }
 
     RunContextLossTimer();
 
     {
         ScopedMaskWorkaround autoMask(*this);
 
-        if (gl->IsSupported(gl::GLFeature::draw_range_elements)) {
+        if (upperBound && gl->IsSupported(gl::GLFeature::draw_range_elements)) {
             gl->fDrawRangeElements(mode, 0, upperBound, count, type,
                                    reinterpret_cast<GLvoid*>(byteOffset));
         } else {
             gl->fDrawElements(mode, count, type,
                               reinterpret_cast<GLvoid*>(byteOffset));
         }
     }
 
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -92,16 +92,17 @@ static const char *sExtensionNames[] = {
     "GL_ARB_geometry_shader4",
     "GL_ARB_half_float_pixel",
     "GL_ARB_instanced_arrays",
     "GL_ARB_internalformat_query",
     "GL_ARB_invalidate_subdata",
     "GL_ARB_map_buffer_range",
     "GL_ARB_occlusion_query2",
     "GL_ARB_pixel_buffer_object",
+    "GL_ARB_robust_buffer_access_behavior",
     "GL_ARB_robustness",
     "GL_ARB_sampler_objects",
     "GL_ARB_sync",
     "GL_ARB_texture_compression",
     "GL_ARB_texture_float",
     "GL_ARB_texture_non_power_of_two",
     "GL_ARB_texture_rectangle",
     "GL_ARB_texture_storage",
@@ -143,16 +144,17 @@ static const char *sExtensionNames[] = {
     "GL_EXT_texture_storage",
     "GL_EXT_timer_query",
     "GL_EXT_transform_feedback",
     "GL_EXT_unpack_subimage",
     "GL_IMG_read_format",
     "GL_IMG_texture_compression_pvrtc",
     "GL_IMG_texture_npot",
     "GL_KHR_debug",
+    "GL_KHR_robust_buffer_access_behavior",
     "GL_NV_draw_instanced",
     "GL_NV_fence",
     "GL_NV_framebuffer_blit",
     "GL_NV_geometry_program4",
     "GL_NV_half_float",
     "GL_NV_instanced_arrays",
     "GL_NV_transform_feedback",
     "GL_NV_transform_feedback2",
@@ -1637,16 +1639,29 @@ GLContext::InitWithPrefix(const char *pr
             fDebugMessageCallback(&StaticDebugCallback, (void*)this);
             fDebugMessageControl(LOCAL_GL_DONT_CARE,
                                  LOCAL_GL_DONT_CARE,
                                  LOCAL_GL_DONT_CARE,
                                  0, nullptr,
                                  true);
         }
 
+        // Until ANGLE supports robust_buffer_access_behavior explicitly, we'll need to
+        // add it ourselves for D3D10+. (D3D10+ always supports
+        // robust_buffer_access_behavior)
+        if (IsANGLE()) {
+            const char* renderer = (const char*)fGetString(LOCAL_GL_RENDERER);
+            if (strstr(renderer, "Direct3D10") || strstr(renderer, "Direct3D11")) {
+                MOZ_ASSERT(!IsSupported(GLFeature::robust_buffer_access_behavior),
+                           "Since ANGLE supports robust_buffer_access_behavior now, we can"
+                           " remove this block of code.");
+                MarkSupported(GLFeature::robust_buffer_access_behavior);
+            }
+        }
+
         reporter.SetSuccessful();
     } else {
         // if initialization fails, ensure all symbols are zero, to avoid hard-to-understand bugs
         mSymbols.Zero();
         NS_WARNING("InitWithPrefix failed!");
     }
 
     mVersionString = nsPrintfCString("%u.%u.%u", mVersion / 100, (mVersion / 10) % 10, mVersion % 10);
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -114,16 +114,17 @@ enum class GLFeature {
     occlusion_query2,
     packed_depth_stencil,
     query_counter,
     query_objects,
     query_time_elapsed,
     read_buffer,
     renderbuffer_color_float,
     renderbuffer_color_half_float,
+    robust_buffer_access_behavior,
     robustness,
     sRGB_framebuffer,
     sRGB_texture,
     sampler_objects,
     standard_derivatives,
     sync,
     texture_3D,
     texture_3D_compressed,
@@ -402,16 +403,17 @@ public:
         ARB_geometry_shader4,
         ARB_half_float_pixel,
         ARB_instanced_arrays,
         ARB_internalformat_query,
         ARB_invalidate_subdata,
         ARB_map_buffer_range,
         ARB_occlusion_query2,
         ARB_pixel_buffer_object,
+        ARB_robust_buffer_access_behavior,
         ARB_robustness,
         ARB_sampler_objects,
         ARB_sync,
         ARB_texture_compression,
         ARB_texture_float,
         ARB_texture_non_power_of_two,
         ARB_texture_rectangle,
         ARB_texture_storage,
@@ -453,16 +455,17 @@ public:
         EXT_texture_storage,
         EXT_timer_query,
         EXT_transform_feedback,
         EXT_unpack_subimage,
         IMG_read_format,
         IMG_texture_compression_pvrtc,
         IMG_texture_npot,
         KHR_debug,
+        KHR_robust_buffer_access_behavior,
         NV_draw_instanced,
         NV_fence,
         NV_framebuffer_blit,
         NV_geometry_program4,
         NV_half_float,
         NV_instanced_arrays,
         NV_transform_feedback,
         NV_transform_feedback2,
@@ -522,16 +525,18 @@ public:
 private:
     std::bitset<size_t(GLFeature::EnumMax)> mAvailableFeatures;
 
     /**
      * Init features regarding OpenGL extension and context version and profile
      */
     void InitFeatures();
 
+    void MarkSupported(GLFeature feature);
+
     /**
      * Mark the feature and associated extensions as unsupported
      */
     void MarkUnsupported(GLFeature feature);
 
     /**
      * Is this feature supported using the core (unsuffixed) symbols?
      */
@@ -3609,16 +3614,20 @@ public:
 protected:
     bool mHeavyGLCallsSinceLastFlush;
 
 public:
     void FlushIfHeavyGLCallsSinceLastFlush();
     static bool ShouldSpew();
     static bool ShouldDumpExts();
     void Readback(SharedSurface* src, gfx::DataSourceSurface* dest);
+
+    virtual bool NeedsDrawElementsValidation() const {
+        return true;
+    }
 };
 
 bool DoesStringMatch(const char* aString, const char *aWantedString);
 
 void SplitByChar(const nsACString& str, const char delim,
                  std::vector<nsCString>* const out);
 
 template<size_t N>
--- a/gfx/gl/GLContextEGL.h
+++ b/gfx/gl/GLContextEGL.h
@@ -65,16 +65,20 @@ public:
     virtual bool IsANGLE() const override {
         return sEGLLibrary.IsANGLE();
     }
 
     virtual bool IsWARP() const override {
         return sEGLLibrary.IsWARP();
     }
 
+    virtual bool NeedsDrawElementsValidation() const override {
+        return true;
+    }
+
     virtual bool BindTexImage() override;
 
     virtual bool ReleaseTexImage() override;
 
     void SetEGLSurfaceOverride(EGLSurface surf);
 
     virtual bool MakeCurrentImpl(bool aForce) override;
 
--- a/gfx/gl/GLContextFeatures.cpp
+++ b/gfx/gl/GLContextFeatures.cpp
@@ -501,16 +501,27 @@ static const FeatureInfo sFeatureInfoArr
         GLContext::Extension_None,
         {
             GLContext::ARB_texture_float,
             GLContext::EXT_color_buffer_half_float,
             GLContext::Extensions_End
         }
     },
     {
+        "robust_buffer_access_behavior",
+        GLVersion::NONE,
+        GLESVersion::NONE,
+        GLContext::Extension_None,
+        {
+            GLContext::ARB_robust_buffer_access_behavior,
+            GLContext::KHR_robust_buffer_access_behavior,
+            GLContext::Extensions_End
+        }
+    },
+    {
         "robustness",
         GLVersion::NONE,
         GLESVersion::NONE,
         GLContext::Extension_None,
         {
             GLContext::ARB_robustness,
             GLContext::EXT_robustness,
             GLContext::Extensions_End
@@ -827,16 +838,22 @@ GLContext::InitFeatures()
         // to an FBO. (bug 843668)
         if (!nsCocoaFeatures::OnLionOrLater())
             MarkUnsupported(GLFeature::sRGB_framebuffer);
 #endif // XP_MACOSX
     }
 }
 
 void
+GLContext::MarkSupported(GLFeature feature)
+{
+    mAvailableFeatures[size_t(feature)] = true;
+}
+
+void
 GLContext::MarkUnsupported(GLFeature feature)
 {
     mAvailableFeatures[size_t(feature)] = false;
 
     const FeatureInfo& featureInfo = GetFeatureInfo(feature);
 
     for (size_t i = 0; true; i++) {
         MOZ_ASSERT(i < kMAX_EXTENSION_GROUP_SIZE, "kMAX_EXTENSION_GROUP_SIZE too small");
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -132,29 +132,35 @@ static bool
 CreateConfig(EGLConfig* aConfig, nsIWidget* aWidget);
 
 // append three zeros at the end of attribs list to work around
 // EGL implementation bugs that iterate until they find 0, instead of
 // EGL_NONE. See bug 948406.
 #define EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS \
      LOCAL_EGL_NONE, 0, 0, 0
 
-static EGLint gTerminationAttribs[] = {
+static EGLint kTerminationAttribs[] = {
     EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
 };
 
-static EGLint gContextAttribs[] = {
+static EGLint kContextAttribs[] = {
     LOCAL_EGL_CONTEXT_CLIENT_VERSION, 2,
     EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
 };
 
-static EGLint gContextAttribsRobustness[] = {
+static EGLint kContextAttribsRobustness[] = {
     LOCAL_EGL_CONTEXT_CLIENT_VERSION, 2,
-    //LOCAL_EGL_CONTEXT_ROBUST_ACCESS_EXT, LOCAL_EGL_TRUE,
-    LOCAL_EGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_EXT, LOCAL_EGL_LOSE_CONTEXT_ON_RESET_EXT,
+    LOCAL_EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, LOCAL_EGL_LOSE_CONTEXT_ON_RESET_EXT,
+    EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
+};
+
+static EGLint kContextAttribsRobustAccess[] = {
+    LOCAL_EGL_CONTEXT_CLIENT_VERSION, 2,
+    LOCAL_EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, LOCAL_EGL_TRUE,
+    LOCAL_EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, LOCAL_EGL_LOSE_CONTEXT_ON_RESET_EXT,
     EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
 };
 
 static int
 next_power_of_two(int v)
 {
     v--;
     v |= v >> 1;
@@ -496,56 +502,69 @@ GLContextEGL::CreateSurfaceForWindow(nsI
 /* static */ void
 GLContextEGL::DestroySurface(EGLSurface aSurface)
 {
     if (aSurface != EGL_NO_SURFACE) {
         sEGLLibrary.fDestroySurface(EGL_DISPLAY(), aSurface);
     }
 }
 
+static EGLContext
+CreateContextForShareContext(EGLDisplay display, EGLConfig config,
+                             EGLContext shareContext)
+{
+    EGLContext context = nullptr;
+
+    if (sEGLLibrary.HasRobustness()) {
+        context = sEGLLibrary.fCreateContext(EGL_DISPLAY(), config, shareContext,
+                                             kContextAttribsRobustAccess);
+        if (!context) {
+            context = sEGLLibrary.fCreateContext(EGL_DISPLAY(), config, shareContext,
+                                                 kContextAttribsRobustness);
+        }
+    }
+
+    if (!context) {
+        context = sEGLLibrary.fCreateContext(EGL_DISPLAY(), config, shareContext,
+                                             kContextAttribs);
+    }
+
+    return context;
+}
+
 already_AddRefed<GLContextEGL>
 GLContextEGL::CreateGLContext(const SurfaceCaps& caps,
                 GLContextEGL *shareContext,
                 bool isOffscreen,
                 EGLConfig config,
                 EGLSurface surface)
 {
     if (sEGLLibrary.fBindAPI(LOCAL_EGL_OPENGL_ES_API) == LOCAL_EGL_FALSE) {
         NS_WARNING("Failed to bind API to GLES!");
         return nullptr;
     }
 
-    EGLContext eglShareContext = shareContext ? shareContext->mContext
-                                              : EGL_NO_CONTEXT;
-    EGLint* attribs = sEGLLibrary.HasRobustness() ? gContextAttribsRobustness
-                                                  : gContextAttribs;
+    EGLContext context = nullptr;
+    if (shareContext) {
+        context = CreateContextForShareContext(EGL_DISPLAY(), config,
+                                               shareContext->mContext);
+    }
 
-    EGLContext context = sEGLLibrary.fCreateContext(EGL_DISPLAY(),
-                                                    config,
-                                                    eglShareContext,
-                                                    attribs);
-    if (!context && shareContext) {
+    if (!context) {
         shareContext = nullptr;
-        context = sEGLLibrary.fCreateContext(EGL_DISPLAY(),
-                                              config,
-                                              EGL_NO_CONTEXT,
-                                              attribs);
+        context = CreateContextForShareContext(EGL_DISPLAY(), config, nullptr);
     }
+
     if (!context) {
         NS_WARNING("Failed to create EGLContext!");
         return nullptr;
     }
 
-    nsRefPtr<GLContextEGL> glContext = new GLContextEGL(caps,
-                                                        shareContext,
-                                                        isOffscreen,
-                                                        config,
-                                                        surface,
-                                                        context);
-
+    nsRefPtr<GLContextEGL> glContext = new GLContextEGL(caps, shareContext, isOffscreen,
+                                                        config, surface, context);
     if (!glContext->Init())
         return nullptr;
 
     return glContext.forget();
 }
 
 EGLSurface
 GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(EGLConfig config,
@@ -563,18 +582,18 @@ TRY_AGAIN_POWER_OF_TWO:
     if (bindToTextureFormat != LOCAL_EGL_NONE) {
         pbattrs.AppendElement(LOCAL_EGL_TEXTURE_TARGET);
         pbattrs.AppendElement(LOCAL_EGL_TEXTURE_2D);
 
         pbattrs.AppendElement(LOCAL_EGL_TEXTURE_FORMAT);
         pbattrs.AppendElement(bindToTextureFormat);
     }
 
-    for (size_t i = 0; i < MOZ_ARRAY_LENGTH(gTerminationAttribs); i++) {
-      pbattrs.AppendElement(gTerminationAttribs[i]);
+    for (size_t i = 0; i < MOZ_ARRAY_LENGTH(kTerminationAttribs); i++) {
+      pbattrs.AppendElement(kTerminationAttribs[i]);
     }
 
     surface = sEGLLibrary.fCreatePbufferSurface(EGL_DISPLAY(), config, &pbattrs[0]);
     if (!surface) {
         if (!is_power_of_two(pbsize.width) ||
             !is_power_of_two(pbsize.height))
         {
             if (!is_power_of_two(pbsize.width))
--- a/gfx/gl/GLDefs.h
+++ b/gfx/gl/GLDefs.h
@@ -47,17 +47,16 @@
 // EGL_ANDROID_image_crop
 #define LOCAL_EGL_IMAGE_CROP_LEFT_ANDROID               0x3148
 #define LOCAL_EGL_IMAGE_CROP_TOP_ANDROID                0x3149
 #define LOCAL_EGL_IMAGE_CROP_RIGHT_ANDROID              0x314A
 #define LOCAL_EGL_IMAGE_CROP_BOTTOM_ANDROID             0x314B
 
 // Others
 #define LOCAL_EGL_PRESERVED_RESOURCES                   0x3030
-#define LOCAL_EGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
 
 // ANGLE_platform_angle_d3d
 #define LOCAL_EGL_PLATFORM_ANGLE_ANGLE                  0x3201
 #define LOCAL_EGL_PLATFORM_ANGLE_TYPE_ANGLE             0x3202
 #define LOCAL_EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE  0x3206
 
 #define LOCAL_GL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
 #define LOCAL_GL_CONTEXT_LOST                           0x9242