Bug 1313541 - GetBufferSubData impl. - r=ethlin
MozReview-Commit-ID: BOQYxIAqsDN
--- 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;