Fix canvas and GL uses of DataSourceSurface::GetData. (bug 1405390 part 2, r=jgilbert)
authorDavid Anderson <danderson@mozilla.com>
Thu, 09 Nov 2017 00:43:30 -0800
changeset 390965 3ae8914a63408662ab4fc26f93e14b8976e33d71
parent 390964 21cfd71761e89ac83fb84bc80fa08a56aff8c4ce
child 390966 b804f968bd3260a45982e4a3d59d7976d31df1b5
push id97153
push userdanderson@mozilla.com
push dateThu, 09 Nov 2017 15:39:40 +0000
treeherdermozilla-inbound@9ae742527820 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert
bugs1405390
milestone58.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
Fix canvas and GL uses of DataSourceSurface::GetData. (bug 1405390 part 2, r=jgilbert)
dom/canvas/CanvasRenderingContext2D.cpp
gfx/gl/GLReadTexImageHelper.cpp
gfx/gl/GLUploadHelpers.cpp
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -6010,16 +6010,17 @@ CanvasRenderingContext2D::PutImageData_e
   // getImageData() and putImageData() methods.
   const gfx::Rect putRect(dirtyRect);
   EnsureTarget(&putRect);
 
   if (!IsTargetValid()) {
     return NS_ERROR_FAILURE;
   }
 
+  DataSourceSurface::MappedSurface map;
   RefPtr<DataSourceSurface> sourceSurface;
   uint8_t* lockedBits = nullptr;
   uint8_t* dstData;
   IntSize dstSize;
   int32_t dstStride;
   SurfaceFormat dstFormat;
   if (mTarget->LockBits(&lockedBits, &dstSize, &dstStride, &dstFormat)) {
     dstData = lockedBits + dirtyRect.y * dstStride + dirtyRect.x * 4;
@@ -6031,35 +6032,40 @@ CanvasRenderingContext2D::PutImageData_e
 
     // In certain scenarios, requesting larger than 8k image fails.  Bug 803568
     // covers the details of how to run into it, but the full detailed
     // investigation hasn't been done to determine the underlying cause.  We
     // will just handle the failure to allocate the surface to avoid a crash.
     if (!sourceSurface) {
       return NS_ERROR_FAILURE;
     }
-    dstData = sourceSurface->GetData();
+    if (!sourceSurface->Map(DataSourceSurface::READ_WRITE, &map)) {
+      return NS_ERROR_FAILURE;
+    }
+
+    dstData = map.mData;
     if (!dstData) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
-    dstStride = sourceSurface->Stride();
+    dstStride = map.mStride;
     dstFormat = sourceSurface->GetFormat();
   }
 
   IntRect srcRect = dirtyRect - IntPoint(aX, aY);
   uint8_t* srcData = aArray->Data() + srcRect.y * (aW * 4) + srcRect.x * 4;
 
   PremultiplyData(srcData, aW * 4, SurfaceFormat::R8G8B8A8,
                   dstData, dstStride,
                   mOpaque ? SurfaceFormat::X8R8G8B8_UINT32 : SurfaceFormat::A8R8G8B8_UINT32,
                   dirtyRect.Size());
 
   if (lockedBits) {
     mTarget->ReleaseBits(lockedBits);
   } else if (sourceSurface) {
+    sourceSurface->Unmap();
     mTarget->CopySurface(sourceSurface, dirtyRect - dirtyRect.TopLeft(), dirtyRect.TopLeft());
   }
 
   Redraw(gfx::Rect(dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height));
 
   return NS_OK;
 }
 
--- a/gfx/gl/GLReadTexImageHelper.cpp
+++ b/gfx/gl/GLReadTexImageHelper.cpp
@@ -385,30 +385,32 @@ ReadPixelsIntoDataSurface(GLContext* gl,
                                                               readFormatGFX,
                                                               stride);
         if (NS_WARN_IF(!tempSurf)) {
             return;
         }
 
         readSurf = tempSurf;
     }
+
+    DataSourceSurface::ScopedMap map(readSurf, DataSourceSurface::READ_WRITE);
     MOZ_ASSERT(readAlignment);
-    MOZ_ASSERT(reinterpret_cast<uintptr_t>(readSurf->GetData()) % readAlignment == 0);
+    MOZ_ASSERT(reinterpret_cast<uintptr_t>(map.GetData()) % readAlignment == 0);
 
     GLsizei width = dest->GetSize().width;
     GLsizei height = dest->GetSize().height;
 
     {
         ScopedPackState safePackState(gl);
         gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, readAlignment);
 
         gl->fReadPixels(0, 0,
                         width, height,
                         readFormat, readType,
-                        readSurf->GetData());
+                        map.GetData());
     }
 
     if (readSurf != dest) {
         MOZ_ASSERT(readFormat == LOCAL_GL_RGBA);
         MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_BYTE);
         gfx::Factory::CopyDataSourceSurface(readSurf, dest);
     }
 }
@@ -470,17 +472,18 @@ ReadBackSurface(GLContext* gl, GLuint aT
     }
 
     uint32_t currentPackAlignment = 0;
     gl->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, (GLint*)&currentPackAlignment);
     if (currentPackAlignment != 4) {
         gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
     }
 
-    gl->fGetTexImage(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, surf->GetData());
+    DataSourceSurface::ScopedMap map(surf, DataSourceSurface::READ);
+    gl->fGetTexImage(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, map.GetData());
 
     if (currentPackAlignment != 4) {
         gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
     }
 
     if (aFormat == SurfaceFormat::R8G8B8A8 || aFormat == SurfaceFormat::R8G8B8X8) {
         SwapRAndBComponents(surf);
     }
--- a/gfx/gl/GLUploadHelpers.cpp
+++ b/gfx/gl/GLUploadHelpers.cpp
@@ -534,20 +534,20 @@ UploadSurfaceToTexture(GLContext* gl,
                        GLuint aTexture,
                        const gfx::IntSize& aSize,
                        size_t* aOutUploadSize,
                        bool aNeedInit,
                        const gfx::IntPoint& aSrcPoint,
                        GLenum aTextureUnit,
                        GLenum aTextureTarget)
 {
-
-    int32_t stride = aSurface->Stride();
+    DataSourceSurface::ScopedMap map(aSurface, DataSourceSurface::READ);
+    int32_t stride = map.GetStride();
     SurfaceFormat format = aSurface->GetFormat();
-    unsigned char* data = aSurface->GetData() +
+    unsigned char* data = map.GetData() +
         DataOffset(aSrcPoint, stride, format);
 
     return UploadImageDataToTexture(gl, data, stride, format,
                                     aDstRegion, aTexture, aSize,
                                     aOutUploadSize, aNeedInit,
                                     aTextureUnit, aTextureTarget);
 }