From ba964b1f9c52d993520caa731f40c6723ebbcd12 Mon Sep 17 00:00:00 2001 From: Jukka Jylanki Date: Wed, 14 Oct 2015 11:18:19 +0530 Subject: [PATCH] Bug 1147441 - Add SharedArrayBuffer support to WebGL and WebGL 2. r=jgilbert, r=bzbarsky --HG-- extra : histedit_source : 141390e44859f0cdb1692979f08f873ad3480754 --- dom/canvas/WebGL2Context.h | 17 +- dom/canvas/WebGL2ContextBuffers.cpp | 31 ++- dom/canvas/WebGL2ContextTextures.cpp | 8 +- dom/canvas/WebGLContext.h | 35 ++- dom/canvas/WebGLContextBuffers.cpp | 188 ++++++++-------- dom/canvas/WebGLContextGL.cpp | 39 +++- dom/canvas/WebGLContextTextures.cpp | 8 +- dom/canvas/WebGLTexture.h | 17 +- dom/canvas/WebGLTextureUpload.cpp | 66 +++--- dom/canvas/test/webgl-mochitest.ini | 1 + .../webgl-mochitest/test_sab_with_webgl.html | 200 ++++++++++++++++++ dom/webidl/WebGL2RenderingContext.webidl | 9 +- dom/webidl/WebGLRenderingContext.webidl | 14 +- 13 files changed, 440 insertions(+), 193 deletions(-) create mode 100644 dom/canvas/test/webgl-mochitest/test_sab_with_webgl.html diff --git a/dom/canvas/WebGL2Context.h b/dom/canvas/WebGL2Context.h index 4fe61423e5b7..e3556ed6fd93 100644 --- a/dom/canvas/WebGL2Context.h +++ b/dom/canvas/WebGL2Context.h @@ -24,6 +24,7 @@ class WebGLVertexArrayObject; namespace dom { class OwningUnsignedLongOrUint32ArrayOrBoolean; class OwningWebGLBufferOrLongLong; +class ArrayBufferViewOrSharedArrayBufferView; } // namespace dom class WebGL2Context @@ -51,8 +52,16 @@ public: void CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); + +private: + template + void GetBufferSubDataT(GLenum target, GLintptr offset, const BufferT& data); + +public: void GetBufferSubData(GLenum target, GLintptr offset, const dom::Nullable& maybeData); + void GetBufferSubData(GLenum target, GLintptr offset, + const dom::SharedArrayBuffer& data); // ------------------------------------------------------------------------- @@ -88,12 +97,12 @@ public: void TexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, - const dom::Nullable& pixels, + const dom::Nullable& pixels, ErrorResult& rv); void TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, const dom::Nullable& pixels, + GLenum format, GLenum type, const dom::Nullable& pixels, ErrorResult& rv); void TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, @@ -109,10 +118,10 @@ public: GLint x, GLint y, GLsizei width, GLsizei height); void CompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, - GLint border, GLsizei imageSize, const dom::ArrayBufferView& data); + GLint border, GLsizei imageSize, const dom::ArrayBufferViewOrSharedArrayBufferView& data); void CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLsizei imageSize, const dom::ArrayBufferView& data); + GLenum format, GLsizei imageSize, const dom::ArrayBufferViewOrSharedArrayBufferView& data); // ------------------------------------------------------------------------- diff --git a/dom/canvas/WebGL2ContextBuffers.cpp b/dom/canvas/WebGL2ContextBuffers.cpp index 4446e9ad66cc..97a08e5c584a 100644 --- a/dom/canvas/WebGL2ContextBuffers.cpp +++ b/dom/canvas/WebGL2ContextBuffers.cpp @@ -138,9 +138,12 @@ WebGL2Context::CopyBufferSubData(GLenum readTarget, GLenum writeTarget, } } +// BufferT may be one of +// const dom::ArrayBuffer& +// const dom::SharedArrayBuffer& +template void -WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset, - const dom::Nullable& maybeData) +WebGL2Context::GetBufferSubDataT(GLenum target, GLintptr offset, const BufferT& data) { if (IsContextLost()) return; @@ -159,11 +162,6 @@ WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset, if (offset < 0) return ErrorInvalidValue("getBufferSubData: negative offset"); - // If returnedData is null then an INVALID_VALUE error is - // generated. - if (maybeData.IsNull()) - return ErrorInvalidValue("getBufferSubData: returnedData is null"); - WebGLRefPtr& bufferSlot = GetBufferSlotByTarget(target); WebGLBuffer* boundBuffer = bufferSlot.get(); if (!boundBuffer) @@ -171,7 +169,6 @@ WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset, // If offset + returnedData.byteLength would extend beyond the end // of the buffer an INVALID_VALUE error is generated. - const dom::ArrayBuffer& data = maybeData.Value(); data.ComputeLengthAndData(); CheckedInt neededByteLength = CheckedInt(offset) + data.Length(); @@ -225,4 +222,22 @@ WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset, } } +void WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset, + const dom::Nullable& maybeData) +{ + // If returnedData is null then an INVALID_VALUE error is + // generated. + if (maybeData.IsNull()) + return ErrorInvalidValue("getBufferSubData: returnedData is null"); + + const dom::ArrayBuffer& data = maybeData.Value(); + GetBufferSubDataT(target, offset, data); +} + +void WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset, + const dom::SharedArrayBuffer& data) +{ + GetBufferSubDataT(target, offset, data); +} + } // namespace mozilla diff --git a/dom/canvas/WebGL2ContextTextures.cpp b/dom/canvas/WebGL2ContextTextures.cpp index 45911cff98c3..3af21102527d 100644 --- a/dom/canvas/WebGL2ContextTextures.cpp +++ b/dom/canvas/WebGL2ContextTextures.cpp @@ -39,7 +39,7 @@ void WebGL2Context::TexImage3D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum unpackFormat, GLenum unpackType, - const dom::Nullable& maybeView, + const dom::Nullable& maybeView, ErrorResult& out_rv) { const char funcName[] = "texImage3D"; @@ -59,7 +59,7 @@ WebGL2Context::TexSubImage3D(GLenum rawTexImageTarget, GLint level, GLint xOffset, GLint yOffset, GLint zOffset, GLsizei width, GLsizei height, GLsizei depth, GLenum unpackFormat, GLenum unpackType, - const dom::Nullable& maybeView, + const dom::Nullable& maybeView, ErrorResult& out_rv) { const char funcName[] = "texSubImage3D"; @@ -95,7 +95,7 @@ WebGL2Context::CopyTexSubImage3D(GLenum target, GLint level, void WebGL2Context::CompressedTexImage3D(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, - GLint border, GLsizei imageSize, const dom::ArrayBufferView& view) + GLint border, GLsizei imageSize, const dom::ArrayBufferViewOrSharedArrayBufferView& view) { GenerateWarning("compressedTexImage3D: Not implemented."); } @@ -103,7 +103,7 @@ WebGL2Context::CompressedTexImage3D(GLenum target, GLint level, GLenum internalF void WebGL2Context::CompressedTexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset, GLint zOffset, GLsizei width, GLsizei height, GLsizei depth, - GLenum unpackFormat, GLsizei imageSize, const dom::ArrayBufferView& view) + GLenum unpackFormat, GLsizei imageSize, const dom::ArrayBufferViewOrSharedArrayBufferView& view) { GenerateWarning("compressedTexSubImage3D: Not implemented."); } diff --git a/dom/canvas/WebGLContext.h b/dom/canvas/WebGLContext.h index 9bf80161897d..7badc1320f3a 100644 --- a/dom/canvas/WebGLContext.h +++ b/dom/canvas/WebGLContext.h @@ -45,7 +45,7 @@ #include "mozilla/dom/HTMLCanvasElement.h" #include "nsWrapperCache.h" #include "nsLayoutUtils.h" - +#include "mozilla/dom/UnionTypes.h" class nsIDocShell; @@ -100,6 +100,7 @@ class Element; class ImageData; class OwningHTMLCanvasElementOrOffscreenCanvas; struct WebGLContextAttributes; +class ArrayBufferViewOrSharedArrayBufferView; template struct Nullable; } // namespace dom @@ -528,7 +529,7 @@ public: void PolygonOffset(GLfloat factor, GLfloat units); void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, - const dom::Nullable& pixels, + const dom::Nullable& pixels, ErrorResult& rv); void RenderbufferStorage(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height); @@ -749,8 +750,8 @@ public: WebGLintptr offset, WebGLsizeiptr size); private: - void BufferDataUnchecked(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage); - void BufferData(GLenum target, WebGLsizeiptr size, void* data, GLenum usage); + template + void BufferDataT(GLenum target, const BufferT& data, GLenum usage); public: void BufferData(GLenum target, WebGLsizeiptr size, GLenum usage); @@ -758,16 +759,25 @@ public: GLenum usage); void BufferData(GLenum target, const dom::Nullable& maybeData, GLenum usage); + void BufferData(GLenum target, const dom::SharedArrayBuffer& data, + GLenum usage); + void BufferData(GLenum target, const dom::SharedArrayBufferView& data, + GLenum usage); private: - void BufferSubDataUnchecked(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data); - void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data); + template + void BufferSubDataT(GLenum target, WebGLsizeiptr byteOffset, + const BufferT& data); public: void BufferSubData(GLenum target, WebGLsizeiptr byteOffset, const dom::ArrayBufferView& data); void BufferSubData(GLenum target, WebGLsizeiptr byteOffset, const dom::Nullable& maybeData); + void BufferSubData(GLenum target, WebGLsizeiptr byteOffset, + const dom::SharedArrayBuffer& data); + void BufferSubData(GLenum target, WebGLsizeiptr byteOffset, + const dom::SharedArrayBufferView& data); already_AddRefed CreateBuffer(); void DeleteBuffer(WebGLBuffer* buf); bool IsBuffer(WebGLBuffer* buf); @@ -864,10 +874,10 @@ protected: public: void CompressedTexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, - const dom::ArrayBufferView& view); + const dom::ArrayBufferViewOrSharedArrayBufferView& view); void CompressedTexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset, GLsizei width, GLsizei height, - GLenum unpackFormat, const dom::ArrayBufferView& view); + GLenum unpackFormat, const dom::ArrayBufferViewOrSharedArrayBufferView& view); void CopyTexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); @@ -878,7 +888,7 @@ public: void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLenum unpackFormat, GLenum unpackType, - const dom::Nullable& maybeView, + const dom::Nullable& maybeView, ErrorResult& out_rv); void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat, GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData, @@ -891,7 +901,7 @@ public: void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset, GLsizei width, GLsizei height, GLenum unpackFormat, GLenum unpackType, - const dom::Nullable& maybeView, + const dom::Nullable& maybeView, ErrorResult& out_rv); void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset, GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData, @@ -1634,6 +1644,11 @@ ValidateTexImageTarget(WebGLContext* webgl, GLenum rawTexImageTarget, // Returns x rounded to the next highest multiple of y. CheckedUint32 RoundedToNextMultipleOf(CheckedUint32 x, CheckedUint32 y); +void +ComputeLengthAndData(const dom::ArrayBufferViewOrSharedArrayBufferView& view, + void** const out_data, size_t* const out_length, + js::Scalar::Type* const out_type); + } // namespace mozilla #endif diff --git a/dom/canvas/WebGLContextBuffers.cpp b/dom/canvas/WebGLContextBuffers.cpp index f0d419df69ea..bc25daa2ce73 100644 --- a/dom/canvas/WebGLContextBuffers.cpp +++ b/dom/canvas/WebGLContextBuffers.cpp @@ -182,25 +182,25 @@ WebGLContext::BufferData(GLenum target, WebGLsizeiptr size, GLenum usage) } } +// BufferT may be one of +// const dom::ArrayBuffer& +// const dom::SharedArrayBuffer& +// const dom::ArrayBufferView& +// const dom::SharedArrayBufferView& +template void -WebGLContext::BufferData(GLenum target, - const dom::Nullable& maybeData, - GLenum usage) +WebGLContext::BufferDataT(GLenum target, + const BufferT& data, + GLenum usage) { if (IsContextLost()) return; - if (maybeData.IsNull()) { - // see http://www.khronos.org/bugzilla/show_bug.cgi?id=386 - return ErrorInvalidValue("bufferData: null object passed"); - } - if (!ValidateBufferTarget(target, "bufferData")) return; const WebGLRefPtr& bufferSlot = GetBufferSlotByTarget(target); - const dom::ArrayBuffer& data = maybeData.Value(); data.ComputeLengthAndData(); // Careful: data.Length() could conceivably be any uint32_t, but GLsizeiptr @@ -231,20 +231,61 @@ WebGLContext::BufferData(GLenum target, return ErrorOutOfMemory("bufferData: out of memory"); } +void +WebGLContext::BufferData(GLenum target, + const dom::SharedArrayBuffer& data, + GLenum usage) +{ + BufferDataT(target, data, usage); +} + +void +WebGLContext::BufferData(GLenum target, + const dom::Nullable& maybeData, + GLenum usage) +{ + if (maybeData.IsNull()) { + // see http://www.khronos.org/bugzilla/show_bug.cgi?id=386 + return ErrorInvalidValue("bufferData: null object passed"); + } + BufferDataT(target, maybeData.Value(), usage); +} + void WebGLContext::BufferData(GLenum target, const dom::ArrayBufferView& data, GLenum usage) +{ + BufferDataT(target, data, usage); +} + +void +WebGLContext::BufferData(GLenum target, const dom::SharedArrayBufferView& data, + GLenum usage) +{ + BufferDataT(target, data, usage); +} + +// BufferT may be one of +// const dom::ArrayBuffer& +// const dom::SharedArrayBuffer& +// const dom::ArrayBufferView& +// const dom::SharedArrayBufferView& +template +void +WebGLContext::BufferSubDataT(GLenum target, + WebGLsizeiptr byteOffset, + const BufferT& data) { if (IsContextLost()) return; - if (!ValidateBufferTarget(target, "bufferData")) + if (!ValidateBufferTarget(target, "bufferSubData")) return; WebGLRefPtr& bufferSlot = GetBufferSlotByTarget(target); - if (!ValidateBufferUsageEnum(usage, "bufferData: usage")) - return; + if (byteOffset < 0) + return ErrorInvalidValue("bufferSubData: negative offset"); WebGLBuffer* boundBuffer = bufferSlot.get(); if (!boundBuffer) @@ -252,119 +293,60 @@ WebGLContext::BufferData(GLenum target, const dom::ArrayBufferView& data, data.ComputeLengthAndData(); - // Careful: data.Length() could conceivably be any uint32_t, but GLsizeiptr - // is like intptr_t. - if (!CheckedInt(data.Length()).isValid()) - return ErrorOutOfMemory("bufferData: bad size"); + CheckedInt checked_neededByteLength = + CheckedInt(byteOffset) + data.Length(); - InvalidateBufferFetching(); - MakeContextCurrent(); - - GLenum error = CheckedBufferData(target, data.Length(), data.Data(), usage); - if (error) { - GenerateWarning("bufferData generated error %s", ErrorName(error)); + if (!checked_neededByteLength.isValid()) { + ErrorInvalidValue("bufferSubData: Integer overflow computing the needed" + " byte length."); return; } - boundBuffer->SetByteLength(data.Length()); - if (!boundBuffer->ElementArrayCacheBufferData(data.Data(), data.Length())) - return ErrorOutOfMemory("bufferData: out of memory"); + if (checked_neededByteLength.value() > boundBuffer->ByteLength()) { + ErrorInvalidValue("bufferSubData: Not enough data. Operation requires" + " %d bytes, but buffer only has %d bytes.", + checked_neededByteLength.value(), + boundBuffer->ByteLength()); + return; + } + + boundBuffer->ElementArrayCacheBufferSubData(byteOffset, data.Data(), + data.Length()); + + MakeContextCurrent(); + gl->fBufferSubData(target, byteOffset, data.Length(), data.Data()); } void WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset, const dom::Nullable& maybeData) { - if (IsContextLost()) - return; - if (maybeData.IsNull()) { // see http://www.khronos.org/bugzilla/show_bug.cgi?id=386 return; } + BufferSubDataT(target, byteOffset, maybeData.Value()); +} - if (!ValidateBufferTarget(target, "bufferSubData")) - return; - - WebGLRefPtr& bufferSlot = GetBufferSlotByTarget(target); - - if (byteOffset < 0) - return ErrorInvalidValue("bufferSubData: negative offset"); - - WebGLBuffer* boundBuffer = bufferSlot.get(); - if (!boundBuffer) - return ErrorInvalidOperation("bufferData: no buffer bound!"); - - const dom::ArrayBuffer& data = maybeData.Value(); - data.ComputeLengthAndData(); - - CheckedInt checked_neededByteLength = - CheckedInt(byteOffset) + data.Length(); - - if (!checked_neededByteLength.isValid()) { - ErrorInvalidValue("bufferSubData: Integer overflow computing the needed" - " byte length."); - return; - } - - if (checked_neededByteLength.value() > boundBuffer->ByteLength()) { - ErrorInvalidValue("bufferSubData: Not enough data. Operation requires" - " %d bytes, but buffer only has %d bytes.", - checked_neededByteLength.value(), - boundBuffer->ByteLength()); - return; - } - - boundBuffer->ElementArrayCacheBufferSubData(byteOffset, data.Data(), - data.Length()); - - MakeContextCurrent(); - gl->fBufferSubData(target, byteOffset, data.Length(), data.Data()); +void +WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset, + const dom::SharedArrayBuffer& data) +{ + BufferSubDataT(target, byteOffset, data); } void WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset, const dom::ArrayBufferView& data) { - if (IsContextLost()) - return; + BufferSubDataT(target, byteOffset, data); +} - if (!ValidateBufferTarget(target, "bufferSubData")) - return; - - WebGLRefPtr& bufferSlot = GetBufferSlotByTarget(target); - - if (byteOffset < 0) - return ErrorInvalidValue("bufferSubData: negative offset"); - - WebGLBuffer* boundBuffer = bufferSlot.get(); - if (!boundBuffer) - return ErrorInvalidOperation("bufferSubData: no buffer bound!"); - - data.ComputeLengthAndData(); - - CheckedInt checked_neededByteLength = - CheckedInt(byteOffset) + data.Length(); - - if (!checked_neededByteLength.isValid()) { - ErrorInvalidValue("bufferSubData: Integer overflow computing the needed" - " byte length."); - return; - } - - if (checked_neededByteLength.value() > boundBuffer->ByteLength()) { - ErrorInvalidValue("bufferSubData: Not enough data. Operation requires" - " %d bytes, but buffer only has %d bytes.", - checked_neededByteLength.value(), - boundBuffer->ByteLength()); - return; - } - - boundBuffer->ElementArrayCacheBufferSubData(byteOffset, data.Data(), - data.Length()); - - MakeContextCurrent(); - gl->fBufferSubData(target, byteOffset, data.Length(), data.Data()); +void +WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset, + const dom::SharedArrayBufferView& data) +{ + BufferSubDataT(target, byteOffset, data); } already_AddRefed diff --git a/dom/canvas/WebGLContextGL.cpp b/dom/canvas/WebGLContextGL.cpp index 53bd8d8e8ea5..4b70290cff7a 100644 --- a/dom/canvas/WebGLContextGL.cpp +++ b/dom/canvas/WebGLContextGL.cpp @@ -1381,10 +1381,32 @@ IsFormatAndTypeUnpackable(GLenum format, GLenum type) } } +// This function is temporary, and will be removed once https://bugzilla.mozilla.org/show_bug.cgi?id=1176214 lands, which will +// collapse the SharedArrayBufferView and ArrayBufferView into one. +void +ComputeLengthAndData(const dom::ArrayBufferViewOrSharedArrayBufferView& view, + void** const out_data, size_t* const out_length, + js::Scalar::Type* const out_type) +{ + if (view.IsArrayBufferView()) { + const dom::ArrayBufferView& pixbuf = view.GetAsArrayBufferView(); + pixbuf.ComputeLengthAndData(); + *out_length = pixbuf.Length(); + *out_data = pixbuf.Data(); + *out_type = JS_GetArrayBufferViewType(pixbuf.Obj()); + } else { + const dom::SharedArrayBufferView& pixbuf = view.GetAsSharedArrayBufferView(); + pixbuf.ComputeLengthAndData(); + *out_length = pixbuf.Length(); + *out_data = pixbuf.Data(); + *out_type = JS_GetSharedArrayBufferViewType(pixbuf.Obj()); + } +} + void WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, - GLenum type, const dom::Nullable& pixels, + GLenum type, const dom::Nullable& pixels, ErrorResult& rv) { if (IsContextLost()) @@ -1460,8 +1482,13 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width, MOZ_CRASH("bad `type`"); } - const dom::ArrayBufferView& pixbuf = pixels.Value(); - int dataType = pixbuf.Type(); + const dom::ArrayBufferViewOrSharedArrayBufferView &view = pixels.Value(); + // Compute length and data. Don't reenter after this point, lest the + // precomputed go out of sync with the instant length/data. + size_t dataByteLen; + void* data; + js::Scalar::Type dataType; + ComputeLengthAndData(view, &data, &dataByteLen, &dataType); // Check the pixels param type if (dataType != requiredDataType) @@ -1479,15 +1506,9 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width, if (!checked_neededByteLength.isValid()) return ErrorInvalidOperation("readPixels: integer overflow computing the needed buffer size"); - // Compute length and data. Don't reenter after this point, lest the - // precomputed go out of sync with the instant length/data. - pixbuf.ComputeLengthAndData(); - - uint32_t dataByteLen = pixbuf.Length(); if (checked_neededByteLength.value() > dataByteLen) return ErrorInvalidOperation("readPixels: buffer too small"); - void* data = pixbuf.Data(); if (!data) { ErrorOutOfMemory("readPixels: buffer storage is null. Did we run out of memory?"); return rv.Throw(NS_ERROR_OUT_OF_MEMORY); diff --git a/dom/canvas/WebGLContextTextures.cpp b/dom/canvas/WebGLContextTextures.cpp index b7f8b81b2524..af8eba5afaca 100644 --- a/dom/canvas/WebGLContextTextures.cpp +++ b/dom/canvas/WebGLContextTextures.cpp @@ -298,7 +298,7 @@ void WebGLContext::TexImage2D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLenum unpackFormat, GLenum unpackType, - const dom::Nullable& maybeView, + const dom::Nullable& maybeView, ErrorResult& out_rv) { TexImageTarget texImageTarget; @@ -356,7 +356,7 @@ void WebGLContext::TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset, GLint yOffset, GLsizei width, GLsizei height, GLenum unpackFormat, GLenum unpackType, - const dom::Nullable& maybeView, + const dom::Nullable& maybeView, ErrorResult& out_rv) { TexImageTarget texImageTarget; @@ -434,7 +434,7 @@ WebGLContext::CopyTexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOf void WebGLContext::CompressedTexImage2D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, - GLint border, const dom::ArrayBufferView& view) + GLint border, const dom::ArrayBufferViewOrSharedArrayBufferView& view) { TexImageTarget texImageTarget; WebGLTexture* tex; @@ -452,7 +452,7 @@ void WebGLContext::CompressedTexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset, GLint yOffset, GLsizei width, GLsizei height, GLenum unpackFormat, - const dom::ArrayBufferView& view) + const dom::ArrayBufferViewOrSharedArrayBufferView& view) { TexImageTarget texImageTarget; WebGLTexture* tex; diff --git a/dom/canvas/WebGLTexture.h b/dom/canvas/WebGLTexture.h index d35effda70b6..66a5a238ca93 100644 --- a/dom/canvas/WebGLTexture.h +++ b/dom/canvas/WebGLTexture.h @@ -24,6 +24,7 @@ class ErrorResult; namespace dom { class Element; class ImageData; +class ArrayBufferViewOrSharedArrayBufferView; } // namespace dom // Zero is not an integer power of two. @@ -108,24 +109,24 @@ public: void CompressedTexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, - GLint border, const dom::ArrayBufferView& view); + GLint border, const dom::ArrayBufferViewOrSharedArrayBufferView& view); void CompressedTexImage3D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, - const dom::ArrayBufferView& view); + const dom::ArrayBufferViewOrSharedArrayBufferView& view); void CompressedTexSubImage2D(TexImageTarget texImageTarget, GLint level, GLint xOffset, GLint yOffset, GLsizei width, GLsizei height, GLenum unpackFormat, - const dom::ArrayBufferView& view); + const dom::ArrayBufferViewOrSharedArrayBufferView& view); void CompressedTexSubImage3D(TexImageTarget texImageTarget, GLint level, GLint xOffset, GLint yOffset, GLint zOffset, GLsizei width, GLsizei height, GLsizei depth, GLenum unpackFormat, GLsizei imageSize, - const dom::ArrayBufferView& view); + const dom::ArrayBufferViewOrSharedArrayBufferView& view); void CopyTexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat, @@ -144,7 +145,7 @@ public: void TexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLenum unpackFormat, GLenum unpackType, - const dom::Nullable& maybeView, + const dom::Nullable& maybeView, ErrorResult* const out_rv); void TexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat, GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData, @@ -156,7 +157,7 @@ public: void TexImage3D(TexImageTarget target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum unpackFormat, GLenum unpackType, - const dom::Nullable& maybeView, + const dom::Nullable& maybeView, ErrorResult* const out_rv); @@ -169,7 +170,7 @@ public: void TexSubImage2D(TexImageTarget texImageTarget, GLint level, GLint xOffset, GLint yOffset, GLsizei width, GLsizei height, GLenum unpackFormat, GLenum unpackType, - const dom::Nullable& maybeView, + const dom::Nullable& maybeView, ErrorResult* const out_rv); void TexSubImage2D(TexImageTarget texImageTarget, GLint level, GLint xOffset, GLint yOffset, GLenum unpackFormat, GLenum unpackType, @@ -181,7 +182,7 @@ public: void TexSubImage3D(TexImageTarget texImageTarget, GLint level, GLint xOffset, GLint yOffset, GLint zOffset, GLsizei width, GLsizei height, GLsizei depth, GLenum unpackFormat, GLenum unpackType, - const dom::Nullable& maybeView, + const dom::Nullable& maybeView, ErrorResult* const out_rv); void TexSubImage3D(TexImageTarget texImageTarget, GLint level, GLint xOffset, GLint yOffset, GLint zOffset, GLenum unpackFormat, diff --git a/dom/canvas/WebGLTextureUpload.cpp b/dom/canvas/WebGLTextureUpload.cpp index ffb2258a395c..6a6b3f047c80 100644 --- a/dom/canvas/WebGLTextureUpload.cpp +++ b/dom/canvas/WebGLTextureUpload.cpp @@ -58,7 +58,7 @@ WebGLTexture::CompressedTexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, - const dom::ArrayBufferView& view) + const dom::ArrayBufferViewOrSharedArrayBufferView& view) { const WebGLTexImageFunc func = WebGLTexImageFunc::CompTexImage; const WebGLTexDimensions dims = WebGLTexDimensions::Tex2D; @@ -76,9 +76,11 @@ WebGLTexture::CompressedTexImage2D(TexImageTarget texImageTarget, return; } - view.ComputeLengthAndData(); + size_t byteLength; + void* data; + js::Scalar::Type dataType; + ComputeLengthAndData(view, &data, &byteLength, &dataType); - uint32_t byteLength = view.Length(); if (!mContext->ValidateCompTexImageDataSize(level, internalFormat, width, height, byteLength, func, dims)) { return; } @@ -96,7 +98,7 @@ WebGLTexture::CompressedTexImage2D(TexImageTarget texImageTarget, mContext->MakeContextCurrent(); gl::GLContext* gl = mContext->gl; - gl->fCompressedTexImage2D(texImageTarget.get(), level, internalFormat, width, height, border, byteLength, view.Data()); + gl->fCompressedTexImage2D(texImageTarget.get(), level, internalFormat, width, height, border, byteLength, data); SetImageInfo(texImageTarget, level, width, height, 1, internalFormat, WebGLImageDataStatus::InitializedImageData); @@ -106,7 +108,7 @@ void WebGLTexture::CompressedTexSubImage2D(TexImageTarget texImageTarget, GLint level, GLint xOffset, GLint yOffset, GLsizei width, GLsizei height, GLenum internalFormat, - const dom::ArrayBufferView& view) + const dom::ArrayBufferViewOrSharedArrayBufferView& view) { const WebGLTexImageFunc func = WebGLTexImageFunc::CompTexSubImage; const WebGLTexDimensions dims = WebGLTexDimensions::Tex2D; @@ -131,9 +133,11 @@ WebGLTexture::CompressedTexSubImage2D(TexImageTarget texImageTarget, GLint level return mContext->ErrorInvalidOperation("compressedTexImage2D: internalFormat does not match the existing image"); } - view.ComputeLengthAndData(); + size_t byteLength; + void* data; + js::Scalar::Type dataType; + ComputeLengthAndData(view, &data, &byteLength, &dataType); - uint32_t byteLength = view.Length(); if (!mContext->ValidateCompTexImageDataSize(level, internalFormat, width, height, byteLength, func, dims)) return; @@ -161,7 +165,7 @@ WebGLTexture::CompressedTexSubImage2D(TexImageTarget texImageTarget, GLint level mContext->MakeContextCurrent(); gl::GLContext* gl = mContext->gl; - gl->fCompressedTexSubImage2D(texImageTarget.get(), level, xOffset, yOffset, width, height, internalFormat, byteLength, view.Data()); + gl->fCompressedTexSubImage2D(texImageTarget.get(), level, xOffset, yOffset, width, height, internalFormat, byteLength, data); } void @@ -614,23 +618,19 @@ void WebGLTexture::TexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLenum unpackFormat, - GLenum unpackType, const dom::Nullable& maybeView, + GLenum unpackType, const dom::Nullable& maybeView, ErrorResult* const out_rv) { void* data; - uint32_t length; + size_t length; js::Scalar::Type jsArrayType; if (maybeView.IsNull()) { data = nullptr; length = 0; jsArrayType = js::Scalar::MaxTypedArrayViewType; } else { - const dom::ArrayBufferView& view = maybeView.Value(); - view.ComputeLengthAndData(); - - data = view.Data(); - length = view.Length(); - jsArrayType = view.Type(); + const auto& view = maybeView.Value(); + ComputeLengthAndData(view, &data, &length, &jsArrayType); } const char funcName[] = "texImage2D"; @@ -850,14 +850,17 @@ WebGLTexture::TexSubImage2D(TexImageTarget texImageTarget, GLint level, GLint xOffset, GLint yOffset, GLsizei width, GLsizei height, GLenum unpackFormat, GLenum unpackType, - const dom::Nullable& maybeView, + const dom::Nullable& maybeView, ErrorResult* const out_rv) { if (maybeView.IsNull()) return mContext->ErrorInvalidValue("texSubImage2D: pixels must not be null!"); - const dom::ArrayBufferView& view = maybeView.Value(); - view.ComputeLengthAndData(); + const auto& view = maybeView.Value(); + size_t length; + void* data; + js::Scalar::Type jsArrayType; + ComputeLengthAndData(view, &data, &length, &jsArrayType); const char funcName[] = "texSubImage2D"; if (!DoesTargetMatchDimensions(mContext, texImageTarget, 2, funcName)) @@ -865,7 +868,7 @@ WebGLTexture::TexSubImage2D(TexImageTarget texImageTarget, GLint level, return TexSubImage2D_base(texImageTarget, level, xOffset, yOffset, width, height, 0, unpackFormat, unpackType, - view.Data(), view.Length(), view.Type(), + data, length, jsArrayType, WebGLTexelFormat::Auto, false); } @@ -1211,7 +1214,7 @@ void WebGLTexture::TexImage3D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum unpackFormat, GLenum unpackType, - const dom::Nullable& maybeView, + const dom::Nullable& maybeView, ErrorResult* const out_rv) { void* data; @@ -1222,12 +1225,8 @@ WebGLTexture::TexImage3D(TexImageTarget texImageTarget, GLint level, GLenum inte dataLength = 0; jsArrayType = js::Scalar::MaxTypedArrayViewType; } else { - const dom::ArrayBufferView& view = maybeView.Value(); - view.ComputeLengthAndData(); - - data = view.Data(); - dataLength = view.Length(); - jsArrayType = view.Type(); + const auto& view = maybeView.Value(); + ComputeLengthAndData(view, &data, &dataLength, &jsArrayType); } const char funcName[] = "texImage3D"; @@ -1318,14 +1317,17 @@ WebGLTexture::TexSubImage3D(TexImageTarget texImageTarget, GLint level, GLint xOffset, GLint yOffset, GLint zOffset, GLsizei width, GLsizei height, GLsizei depth, GLenum unpackFormat, GLenum unpackType, - const dom::Nullable& maybeView, + const dom::Nullable& maybeView, ErrorResult* const out_rv) { if (maybeView.IsNull()) return mContext->ErrorInvalidValue("texSubImage3D: pixels must not be null!"); - const dom::ArrayBufferView& view = maybeView.Value(); - view.ComputeLengthAndData(); + const auto& view = maybeView.Value(); + void* data; + size_t dataLength; + js::Scalar::Type jsArrayType; + ComputeLengthAndData(view, &data, &dataLength, &jsArrayType); const char funcName[] = "texSubImage3D"; if (!DoesTargetMatchDimensions(mContext, texImageTarget, 3, funcName)) @@ -1358,10 +1360,6 @@ WebGLTexture::TexSubImage3D(TexImageTarget texImageTarget, GLint level, return mContext->ErrorInvalidOperation("texSubImage3D: type differs from that of the existing image"); } - js::Scalar::Type jsArrayType = view.Type(); - void* data = view.Data(); - size_t dataLength = view.Length(); - if (!mContext->ValidateTexInputData(unpackType, jsArrayType, func, dims)) return; diff --git a/dom/canvas/test/webgl-mochitest.ini b/dom/canvas/test/webgl-mochitest.ini index 2f70700a924c..1b20d3cbf1af 100644 --- a/dom/canvas/test/webgl-mochitest.ini +++ b/dom/canvas/test/webgl-mochitest.ini @@ -23,6 +23,7 @@ skip-if = android_version == '10' || android_version == '18' #Android 2.3 and 4. [webgl-mochitest/test_noprog_draw.html] [webgl-mochitest/test_privileged_exts.html] [webgl-mochitest/test_renderer_strings.html] +[webgl-mochitest/test_sab_with_webgl.html] [webgl-mochitest/test_texsubimage_float.html] [webgl-mochitest/test_uninit_data.html] [webgl-mochitest/test_webgl_available.html] diff --git a/dom/canvas/test/webgl-mochitest/test_sab_with_webgl.html b/dom/canvas/test/webgl-mochitest/test_sab_with_webgl.html new file mode 100644 index 000000000000..e92a6568259d --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/test_sab_with_webgl.html @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + diff --git a/dom/webidl/WebGL2RenderingContext.webidl b/dom/webidl/WebGL2RenderingContext.webidl index 3be96123809f..f82d2022ae91 100644 --- a/dom/webidl/WebGL2RenderingContext.webidl +++ b/dom/webidl/WebGL2RenderingContext.webidl @@ -319,6 +319,7 @@ interface WebGL2RenderingContext : WebGLRenderingContext void copyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); void getBufferSubData(GLenum target, GLintptr offset, ArrayBuffer? returnedData); + void getBufferSubData(GLenum target, GLintptr offset, SharedArrayBuffer returnedData); /* Framebuffer objects */ void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, @@ -347,10 +348,10 @@ interface WebGL2RenderingContext : WebGLRenderingContext void texImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, - GLenum type, ArrayBufferView? pixels); + GLenum type, (ArrayBufferView or SharedArrayBufferView)? pixels); [Throws] void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, - ArrayBufferView? pixels); + (ArrayBufferView or SharedArrayBufferView)? pixels); [Throws] void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLenum format, GLenum type, ImageData? data); [Throws] void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, @@ -363,10 +364,10 @@ interface WebGL2RenderingContext : WebGLRenderingContext GLint x, GLint y, GLsizei width, GLsizei height); void compressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, - GLint border, GLsizei imageSize, ArrayBufferView data); + GLint border, GLsizei imageSize, (ArrayBufferView or SharedArrayBufferView) data); void compressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLsizei imageSize, ArrayBufferView data); + GLenum format, GLsizei imageSize, (ArrayBufferView or SharedArrayBufferView) data); /* Programs and shaders */ [WebGLHandlesContextLoss] GLint getFragDataLocation(WebGLProgram? program, DOMString name); diff --git a/dom/webidl/WebGLRenderingContext.webidl b/dom/webidl/WebGLRenderingContext.webidl index 3ab31d10a372..d5859fd6c840 100644 --- a/dom/webidl/WebGLRenderingContext.webidl +++ b/dom/webidl/WebGLRenderingContext.webidl @@ -552,9 +552,13 @@ interface WebGLRenderingContext { void bufferData(GLenum target, GLsizeiptr size, GLenum usage); void bufferData(GLenum target, ArrayBufferView data, GLenum usage); + void bufferData(GLenum target, SharedArrayBufferView data, GLenum usage); void bufferData(GLenum target, ArrayBuffer? data, GLenum usage); + void bufferData(GLenum target, SharedArrayBuffer data, GLenum usage); void bufferSubData(GLenum target, GLintptr offset, ArrayBufferView data); + void bufferSubData(GLenum target, GLintptr offset, SharedArrayBufferView data); void bufferSubData(GLenum target, GLintptr offset, ArrayBuffer? data); + void bufferSubData(GLenum target, GLintptr offset, SharedArrayBuffer data); [WebGLHandlesContextLoss] GLenum checkFramebufferStatus(GLenum target); void clear(GLbitfield mask); @@ -566,11 +570,11 @@ interface WebGLRenderingContext { void compressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, - ArrayBufferView data); + (ArrayBufferView or SharedArrayBufferView) data); void compressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, - ArrayBufferView data); + (ArrayBufferView or SharedArrayBufferView) data); void copyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, @@ -673,7 +677,7 @@ interface WebGLRenderingContext { [Throws] void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, ArrayBufferView? pixels); + GLenum format, GLenum type, (ArrayBufferView or SharedArrayBufferView)? pixels); void renderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); @@ -693,7 +697,7 @@ interface WebGLRenderingContext { [Throws] void texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, - GLenum type, ArrayBufferView? pixels); + GLenum type, (ArrayBufferView or SharedArrayBufferView)? pixels); [Throws] void texImage2D(GLenum target, GLint level, GLenum internalformat, GLenum format, GLenum type, ImageData? pixels); @@ -713,7 +717,7 @@ interface WebGLRenderingContext { [Throws] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLenum type, ArrayBufferView? pixels); + GLenum format, GLenum type, (ArrayBufferView or SharedArrayBufferView)? pixels); [Throws] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLenum format, GLenum type, ImageData? pixels);