Bug 1457546 - Use glMapBufferRange instead of glMapBuffer to capture screenshots r=jgilbert
authorBarret Rennie <barret@brennie.ca>
Tue, 20 Nov 2018 18:32:10 +0000
changeset 503864 99433995b7cd8d51e9a4759cb3b658a00e5ad9e0
parent 503863 a14f9ec04145cc4d4cceeec942c44db12024c323
child 503865 8b1b35582dd7f986619174828bae634511718de9
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert
bugs1457546
milestone65.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 1457546 - Use glMapBufferRange instead of glMapBuffer to capture screenshots r=jgilbert It was pointed out in a review by jgilbert that glMapBuffer only supports writing to the mapped range on an OpenGL ES profile and using it to read is undefined behaviour. We now use glMapBufferRange when available, which does support reading on both OpenGL and OpenGL ES profiles, and allows capturing screenshots on Android. When it is not available, we fall back to glMapBuffer (e.g., for macOS). Differential Revision: https://phabricator.services.mozilla.com/D12341
gfx/gl/GLContext.cpp
gfx/gl/GLContext.h
gfx/gl/GLContextFeatures.cpp
gfx/layers/opengl/CompositorOGL.cpp
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -134,16 +134,17 @@ static const char* const sExtensionNames
     "GL_EXT_draw_instanced",
     "GL_EXT_draw_range_elements",
     "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",
     "GL_EXT_occlusion_query_boolean",
     "GL_EXT_packed_depth_stencil",
     "GL_EXT_read_format_bgra",
     "GL_EXT_robustness",
     "GL_EXT_sRGB",
     "GL_EXT_sRGB_write_control",
     "GL_EXT_shader_texture_lod",
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -435,16 +435,17 @@ public:
         EXT_draw_instanced,
         EXT_draw_range_elements,
         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,
         EXT_occlusion_query_boolean,
         EXT_packed_depth_stencil,
         EXT_read_format_bgra,
         EXT_robustness,
         EXT_sRGB,
         EXT_sRGB_write_control,
         EXT_shader_texture_lod,
--- a/gfx/gl/GLContextFeatures.cpp
+++ b/gfx/gl/GLContextFeatures.cpp
@@ -367,16 +367,17 @@ static const FeatureInfo sFeatureInfoArr
         }
     },
     {
         "map_buffer_range",
         GLVersion::GL3,
         GLESVersion::ES3,
         GLContext::ARB_map_buffer_range,
         {
+            GLContext::EXT_map_buffer_range,
             GLContext::Extensions_End
         }
     },
     {
         "occlusion_query",
         GLVersion::GL2,
         GLESVersion::NONE,
         GLContext::Extension_None,
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -121,32 +121,43 @@ AsyncReadbackBufferOGL::MapAndCopyInto(D
   MOZ_RELEASE_ASSERT(aReadSize <= aSurface->GetSize());
 
   if (!mGL || !mGL->MakeCurrent()) {
     return false;
   }
 
   ScopedPackState scopedPackState(mGL);
   Bind();
-  uint8_t* srcData = static_cast<uint8_t*>(
-    mGL->fMapBuffer(LOCAL_GL_PIXEL_PACK_BUFFER, LOCAL_GL_READ_ONLY));
+
+  const uint8_t *srcData = nullptr;
+  if (mGL->IsSupported(GLFeature::map_buffer_range)) {
+    srcData = static_cast<uint8_t*>(
+      mGL->fMapBufferRange(
+        LOCAL_GL_PIXEL_PACK_BUFFER,
+        0,
+        aReadSize.height * aReadSize.width * 4,
+        LOCAL_GL_MAP_READ_BIT));
+  } else {
+    srcData = static_cast<uint8_t*>(
+      mGL->fMapBuffer(LOCAL_GL_PIXEL_PACK_BUFFER, LOCAL_GL_READ_ONLY));
+  }
 
   if (!srcData) {
     return false;
   }
 
   int32_t srcStride = mSize.width * 4; // Bind() sets an alignment of 1
   DataSourceSurface::ScopedMap map(aSurface, DataSourceSurface::WRITE);
   uint8_t* destData = map.GetData();
   int32_t destStride = map.GetStride();
   SurfaceFormat destFormat = aSurface->GetFormat();
   for (int32_t destRow = 0; destRow < aReadSize.height; destRow++) {
     // Turn srcData upside down during the copy.
     int32_t srcRow = aReadSize.height - 1 - destRow;
-    uint8_t* src = &srcData[srcRow * srcStride];
+    const uint8_t* src = &srcData[srcRow * srcStride];
     uint8_t* dest = &destData[destRow * destStride];
     SwizzleData(src, srcStride, SurfaceFormat::R8G8B8A8,
                 dest, destStride, destFormat, IntSize(aReadSize.width, 1));
   }
 
   mGL->fUnmapBuffer(LOCAL_GL_PIXEL_PACK_BUFFER);
 
   return true;