Bug 1313541 - GetBufferSubData impl. - r=ethlin, a=gchang
authorJeff Gilbert (:jgilbert) <jgilbert@mozilla.com>
Tue, 11 Oct 2016 17:38:45 -0700
changeset 356581 827e25dec6e18e17afc66749c7a591feae61eb8e
parent 356580 9db4213007d93076c10f2fd954830344974185fb
child 356582 103e04e023dffe4c73eba7a78a3ad09fdc7ade23
push id6570
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:26:13 +0000
treeherdermozilla-beta@f455459b2ae5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersethlin, gchang
bugs1313541
milestone51.0a2
Bug 1313541 - GetBufferSubData impl. - r=ethlin, a=gchang MozReview-Commit-ID: BOQYxIAqsDN
dom/canvas/WebGL2Context.h
dom/canvas/WebGL2ContextBuffers.cpp
dom/canvas/WebGLBuffer.cpp
dom/canvas/WebGLContextBuffers.cpp
--- a/dom/canvas/WebGL2Context.h
+++ b/dom/canvas/WebGL2Context.h
@@ -46,18 +46,19 @@ public:
     void CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
                            GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
 
 private:
     template<typename BufferT>
     void GetBufferSubDataT(GLenum target, GLintptr offset, const BufferT& data);
 
 public:
-    void GetBufferSubData(GLenum target, GLintptr offset,
-                          const dom::ArrayBufferView& dstData);
+    void GetBufferSubData(GLenum target, GLintptr srcByteOffset,
+                          const dom::ArrayBufferView& dstData, GLuint dstElemOffset,
+                          GLuint dstElemCountOverride);
 
     // -------------------------------------------------------------------------
     // Framebuffer objects - WebGL2ContextFramebuffers.cpp
 
     void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
                          GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
                          GLbitfield mask, GLenum filter);
     void FramebufferTextureLayer(GLenum target, GLenum attachment, WebGLTexture* texture, GLint level, GLint layer);
--- a/dom/canvas/WebGL2ContextBuffers.cpp
+++ b/dom/canvas/WebGL2ContextBuffers.cpp
@@ -86,49 +86,43 @@ WebGL2Context::CopyBufferSubData(GLenum 
 
     gl->MakeCurrent();
     const ScopedLazyBind readBind(gl, readTarget, readBuffer);
     const ScopedLazyBind writeBind(gl, writeTarget, writeBuffer);
     gl->fCopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size);
 }
 
 void
-WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset,
-                                const dom::ArrayBufferView& data)
+WebGL2Context::GetBufferSubData(GLenum target, GLintptr srcByteOffset,
+                                const dom::ArrayBufferView& dstData, GLuint dstElemOffset,
+                                GLuint dstElemCountOverride)
 {
     const char funcName[] = "getBufferSubData";
     if (IsContextLost())
         return;
 
-    if (!ValidateNonNegative(funcName, "offset", offset))
+    if (!ValidateNonNegative(funcName, "srcByteOffset", srcByteOffset))
         return;
 
+    uint8_t* bytes;
+    size_t byteLen;
+    if (!ValidateArrayBufferView(funcName, dstData, dstElemOffset, dstElemCountOverride,
+                                 &bytes, &byteLen))
+    {
+        return;
+    }
+
+    ////
+
     const auto& buffer = ValidateBufferSelection(funcName, target);
     if (!buffer)
         return;
 
-    ////
-
-    // If offset + returnedData.byteLength would extend beyond the end
-    // of the buffer an INVALID_VALUE error is generated.
-    data.ComputeLengthAndData();
-
-    const auto neededByteLength = CheckedInt<size_t>(offset) + data.LengthAllowShared();
-    if (!neededByteLength.isValid()) {
-        ErrorInvalidValue("%s: Integer overflow computing the needed byte length.",
-                          funcName);
+    if (!buffer->ValidateRange(funcName, srcByteOffset, byteLen))
         return;
-    }
-
-    if (neededByteLength.value() > buffer->ByteLength()) {
-        ErrorInvalidValue("%s: Not enough data. Operation requires %d bytes, but buffer"
-                          " only has %d bytes.",
-                          funcName, neededByteLength.value(), buffer->ByteLength());
-        return;
-    }
 
     ////
 
     if (buffer->mNumActiveTFOs) {
         ErrorInvalidOperation("%s: Buffer is bound to an active transform feedback"
                               " object.",
                               funcName);
         return;
@@ -137,21 +131,29 @@ WebGL2Context::GetBufferSubData(GLenum t
     if (target == LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER &&
         mBoundTransformFeedback->mIsActive)
     {
         ErrorInvalidOperation("%s: Currently bound transform feedback is active.",
                               funcName);
         return;
     }
 
+    if (!CheckedInt<GLsizeiptr>(byteLen).isValid()) {
+        ErrorOutOfMemory("%s: Size too large.", funcName);
+        return;
+    }
+    const GLsizeiptr glByteLen(byteLen);
+
     ////
 
     gl->MakeCurrent();
     const ScopedLazyBind readBind(gl, target, buffer);
 
-    const auto ptr = gl->fMapBufferRange(target, offset, data.LengthAllowShared(),
-                                         LOCAL_GL_MAP_READ_BIT);
+    const auto mappedBytes = gl->fMapBufferRange(target, srcByteOffset, glByteLen,
+                                                 LOCAL_GL_MAP_READ_BIT);
     // Warning: Possibly shared memory.  See bug 1225033.
-    memcpy(data.DataAllowShared(), ptr, data.LengthAllowShared());
+    if (byteLen) {
+        memcpy(bytes, mappedBytes, byteLen);
+    }
     gl->fUnmapBuffer(target);
 }
 
 } // namespace mozilla
--- a/dom/canvas/WebGLBuffer.cpp
+++ b/dom/canvas/WebGLBuffer.cpp
@@ -101,17 +101,17 @@ ValidateBufferUsageEnum(WebGLContext* we
 void
 WebGLBuffer::BufferData(GLenum target, size_t size, const void* data, GLenum usage)
 {
     const char funcName[] = "bufferData";
 
     // Careful: data.Length() could conceivably be any uint32_t, but GLsizeiptr
     // is like intptr_t.
     if (!CheckedInt<GLsizeiptr>(size).isValid())
-        return ErrorOutOfMemory("%s: bad size", funcName);
+        return mContext->ErrorOutOfMemory("%s: bad size", funcName);
 
     if (!ValidateBufferUsageEnum(mContext, funcName, usage))
         return;
 
     if (mNumActiveTFOs) {
         mContext->ErrorInvalidOperation("%s: Buffer is bound to an active transform"
                                         " feedback object.",
                                         funcName);
--- a/dom/canvas/WebGLContextBuffers.cpp
+++ b/dom/canvas/WebGLContextBuffers.cpp
@@ -329,17 +329,17 @@ WebGLContext::BufferData(GLenum target, 
         return;
 
     ////
 
     const UniqueBuffer zeroBuffer(calloc(size, 1));
     if (!zeroBuffer)
         return ErrorOutOfMemory("%s: Failed to allocate zeros.", funcName);
 
-    BufferDataImpl(target, size_t(size), zeroBuffer.get(), usage);
+    BufferDataImpl(target, size_t(size), (const uint8_t*)zeroBuffer.get(), usage);
 }
 
 void
 WebGLContext::BufferData(GLenum target, const dom::SharedArrayBuffer& src, GLenum usage)
 {
     if (IsContextLost())
         return;