Bug 1324312 - Handle alloc failure when uploading texture. r=sotaro a=jcristau
authorJamie Nicol <jnicol@mozilla.com>
Mon, 23 Jan 2017 20:00:05 +0000
changeset 375756 cc00a0e9025fb83a7f2265e02a3e1ad6c3b5c4c8
parent 375755 87ff239bdeb8e12394a069cda2eec29c7765449c
child 375757 faae0d26b4dffa56626ac6964b7697ce09684a74
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssotaro, jcristau
bugs1324312
milestone53.0a2
Bug 1324312 - Handle alloc failure when uploading texture. r=sotaro a=jcristau When GL_UNPACK_ROW_LENGTH is not supported and the source data has a different stride to that of the texture (often because we are uploading only the modified subimage) we allocate a temporary buffer with the correct stride. This was found to be more efficient than uploading each row of texture data individually. Sometimes allocating the buffer will fail, however. In such cases fall back to uploading the texture row-by-row, rather than aborting. MozReview-Commit-ID: E7LE8nHPE0M
gfx/gl/GLUploadHelpers.cpp
--- a/gfx/gl/GLUploadHelpers.cpp
+++ b/gfx/gl/GLUploadHelpers.cpp
@@ -156,40 +156,62 @@ TexSubImage2DWithoutUnpackSubimage(GLCon
                                    GLsizei stride, GLint pixelsize,
                                    GLenum format, GLenum type,
                                    const GLvoid* pixels)
 {
     // Not using the whole row of texture data and GL_UNPACK_ROW_LENGTH
     // isn't supported. We make a copy of the texture data we're using,
     // such that we're using the whole row of data in the copy. This turns
     // out to be more efficient than uploading row-by-row; see bug 698197.
-    unsigned char* newPixels = new unsigned char[width*height*pixelsize];
-    unsigned char* rowDest = newPixels;
-    const unsigned char* rowSource = (const unsigned char*)pixels;
-    for (int h = 0; h < height; h++) {
+    unsigned char* newPixels = new (fallible) unsigned char[width*height*pixelsize];
+
+    if (newPixels) {
+        unsigned char* rowDest = newPixels;
+        const unsigned char* rowSource = (const unsigned char*)pixels;
+        for (int h = 0; h < height; h++) {
             memcpy(rowDest, rowSource, width*pixelsize);
             rowDest += width*pixelsize;
             rowSource += stride;
-    }
+        }
+
+        stride = width*pixelsize;
+        gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
+                         std::min(GetAddressAlignment((ptrdiff_t)newPixels),
+                                  GetAddressAlignment((ptrdiff_t)stride)));
+        gl->fTexSubImage2D(target,
+                           level,
+                           xoffset,
+                           yoffset,
+                           width,
+                           height,
+                           format,
+                           type,
+                           newPixels);
+        delete [] newPixels;
+        gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
 
-    stride = width*pixelsize;
-    gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
-                     std::min(GetAddressAlignment((ptrdiff_t)newPixels),
-                              GetAddressAlignment((ptrdiff_t)stride)));
-    gl->fTexSubImage2D(target,
-                       level,
-                       xoffset,
-                       yoffset,
-                       width,
-                       height,
-                       format,
-                       type,
-                       newPixels);
-    delete [] newPixels;
-    gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
+    } else {
+        // If we did not have sufficient memory for the required
+        // temporary buffer, then fall back to uploading row-by-row.
+        const unsigned char* rowSource = (const unsigned char*)pixels;
+
+        gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
+                         std::min(GetAddressAlignment((ptrdiff_t)pixels),
+                                  GetAddressAlignment((ptrdiff_t)stride)));
+
+        for (int i = 0; i < height; i++) {
+            gl->fTexSubImage2D(target, level,
+                               xoffset, yoffset + i,
+                               width, 1,
+                               format, type, rowSource);
+            rowSource += stride;
+        }
+
+        gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
+    }
 }
 
 static void
 TexSubImage2DHelper(GLContext* gl,
                     GLenum target, GLint level,
                     GLint xoffset, GLint yoffset,
                     GLsizei width, GLsizei height, GLsizei stride,
                     GLint pixelsize, GLenum format,