From feb21260f6df885f687d478d60b0f856a27a76e6 Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Wed, 2 Sep 2015 14:06:58 -0700 Subject: [PATCH] Bug 1200864 - Skip DrawElements buffer validation when we have robust_buffer_access. - r=kamidphish --- dom/canvas/WebGLContextDraw.cpp | 21 +++++---- gfx/gl/GLContext.cpp | 15 +++++++ gfx/gl/GLContext.h | 9 ++++ gfx/gl/GLContextEGL.h | 4 ++ gfx/gl/GLContextFeatures.cpp | 17 ++++++++ gfx/gl/GLContextProviderEGL.cpp | 77 ++++++++++++++++++++------------- gfx/gl/GLDefs.h | 1 - 7 files changed, 106 insertions(+), 38 deletions(-) diff --git a/dom/canvas/WebGLContextDraw.cpp b/dom/canvas/WebGLContextDraw.cpp index 47afcbf0473..e8b6ec984e9 100644 --- a/dom/canvas/WebGLContextDraw.cpp +++ b/dom/canvas/WebGLContextDraw.cpp @@ -254,13 +254,18 @@ WebGLContext::DrawElements_check(GLsizei count, GLenum type, 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) { @@ -322,7 +327,7 @@ WebGLContext::DrawElements(GLenum mode, GLsizei count, GLenum type, { 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(byteOffset)); } else { diff --git a/gfx/gl/GLContext.cpp b/gfx/gl/GLContext.cpp index 3bedf3bbe40..73e44980098 100644 --- a/gfx/gl/GLContext.cpp +++ b/gfx/gl/GLContext.cpp @@ -97,6 +97,7 @@ static const char *sExtensionNames[] = { "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", @@ -148,6 +149,7 @@ static const char *sExtensionNames[] = { "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", @@ -1642,6 +1644,19 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl) 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 diff --git a/gfx/gl/GLContext.h b/gfx/gl/GLContext.h index 0f23d13e718..1aa68ecd51c 100644 --- a/gfx/gl/GLContext.h +++ b/gfx/gl/GLContext.h @@ -119,6 +119,7 @@ enum class GLFeature { read_buffer, renderbuffer_color_float, renderbuffer_color_half_float, + robust_buffer_access_behavior, robustness, sRGB_framebuffer, sRGB_texture, @@ -407,6 +408,7 @@ public: ARB_map_buffer_range, ARB_occlusion_query2, ARB_pixel_buffer_object, + ARB_robust_buffer_access_behavior, ARB_robustness, ARB_sampler_objects, ARB_sync, @@ -458,6 +460,7 @@ public: IMG_texture_compression_pvrtc, IMG_texture_npot, KHR_debug, + KHR_robust_buffer_access_behavior, NV_draw_instanced, NV_fence, NV_framebuffer_blit, @@ -527,6 +530,8 @@ private: */ void InitFeatures(); + void MarkSupported(GLFeature feature); + /** * Mark the feature and associated extensions as unsupported */ @@ -3614,6 +3619,10 @@ public: 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); diff --git a/gfx/gl/GLContextEGL.h b/gfx/gl/GLContextEGL.h index 5a4d3b7222d..e212ee66e7c 100644 --- a/gfx/gl/GLContextEGL.h +++ b/gfx/gl/GLContextEGL.h @@ -70,6 +70,10 @@ public: return sEGLLibrary.IsWARP(); } + virtual bool NeedsDrawElementsValidation() const override { + return true; + } + virtual bool BindTexImage() override; virtual bool ReleaseTexImage() override; diff --git a/gfx/gl/GLContextFeatures.cpp b/gfx/gl/GLContextFeatures.cpp index 780a9950169..2f1c3e9c220 100644 --- a/gfx/gl/GLContextFeatures.cpp +++ b/gfx/gl/GLContextFeatures.cpp @@ -505,6 +505,17 @@ static const FeatureInfo sFeatureInfoArr[] = { 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, @@ -831,6 +842,12 @@ GLContext::InitFeatures() } } +void +GLContext::MarkSupported(GLFeature feature) +{ + mAvailableFeatures[size_t(feature)] = true; +} + void GLContext::MarkUnsupported(GLFeature feature) { diff --git a/gfx/gl/GLContextProviderEGL.cpp b/gfx/gl/GLContextProviderEGL.cpp index c42b56272c2..3bcc8838b63 100644 --- a/gfx/gl/GLContextProviderEGL.cpp +++ b/gfx/gl/GLContextProviderEGL.cpp @@ -137,19 +137,25 @@ CreateConfig(EGLConfig* aConfig, nsIWidget* aWidget); #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 }; @@ -501,6 +507,29 @@ GLContextEGL::DestroySurface(EGLSurface 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::CreateGLContext(const SurfaceCaps& caps, GLContextEGL *shareContext, @@ -513,34 +542,24 @@ GLContextEGL::CreateGLContext(const SurfaceCaps& caps, return nullptr; } - EGLContext eglShareContext = shareContext ? shareContext->mContext - : EGL_NO_CONTEXT; - EGLint* attribs = sEGLLibrary.HasRobustness() ? gContextAttribsRobustness - : gContextAttribs; - - EGLContext context = sEGLLibrary.fCreateContext(EGL_DISPLAY(), - config, - eglShareContext, - attribs); - if (!context && shareContext) { - shareContext = nullptr; - context = sEGLLibrary.fCreateContext(EGL_DISPLAY(), - config, - EGL_NO_CONTEXT, - attribs); + EGLContext context = nullptr; + if (shareContext) { + context = CreateContextForShareContext(EGL_DISPLAY(), config, + shareContext->mContext); } + + if (!context) { + shareContext = nullptr; + context = CreateContextForShareContext(EGL_DISPLAY(), config, nullptr); + } + if (!context) { NS_WARNING("Failed to create EGLContext!"); return nullptr; } - nsRefPtr glContext = new GLContextEGL(caps, - shareContext, - isOffscreen, - config, - surface, - context); - + nsRefPtr glContext = new GLContextEGL(caps, shareContext, isOffscreen, + config, surface, context); if (!glContext->Init()) return nullptr; @@ -568,8 +587,8 @@ TRY_AGAIN_POWER_OF_TWO: 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]); diff --git a/gfx/gl/GLDefs.h b/gfx/gl/GLDefs.h index 18faa79416b..8b22d3e1698 100644 --- a/gfx/gl/GLDefs.h +++ b/gfx/gl/GLDefs.h @@ -52,7 +52,6 @@ // 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