Bug 1313541 - Texture impl. - r=ethlin draft
authorJeff Gilbert (:jgilbert) <jgilbert@mozilla.com>
Tue, 11 Oct 2016 18:54:59 -0700
changeset 430646 cb8133d8437a664cad5e9afae06ceaa126b471f8
parent 430645 d59f68bb917c69e7b3a5f532d3b5bfe2a72c46fc
child 430647 4f00518a90a3528ab3aba585edc69c6226795e98
push id33862
push userbmo:jgilbert@mozilla.com
push dateFri, 28 Oct 2016 02:14:30 +0000
reviewersethlin
bugs1313541
milestone52.0a1
Bug 1313541 - Texture impl. - r=ethlin MozReview-Commit-ID: GEYMTnqC9Q3
dom/canvas/WebGL2Context.h
dom/canvas/WebGL2ContextTextures.cpp
dom/canvas/WebGLContext.h
dom/canvas/WebGLTexture.h
dom/canvas/WebGLTextureUpload.cpp
--- a/dom/canvas/WebGL2Context.h
+++ b/dom/canvas/WebGL2Context.h
@@ -87,41 +87,77 @@ public:
     // -------------------------------------------------------------------------
     // Texture objects - WebGL2ContextTextures.cpp
 
     void TexStorage2D(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width,
                       GLsizei height);
     void TexStorage3D(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width,
                       GLsizei height, GLsizei depth);
 
+    ////
+
+private:
+    void TexImage3D(GLenum target, GLint level, GLenum internalFormat, GLsizei width,
+                    GLsizei height, GLsizei depth, GLint border, GLenum unpackFormat,
+                    GLenum unpackType, const dom::ArrayBufferView* srcView,
+                    GLuint srcElemOffset);
+
+public:
     void TexImage3D(GLenum target, GLint level, GLenum internalFormat, GLsizei width,
                     GLsizei height, GLsizei depth, GLint border, GLenum unpackFormat,
-                    GLenum unpackType, const dom::Nullable<dom::ArrayBufferView>& data);
+                    GLenum unpackType,
+                    const dom::Nullable<dom::ArrayBufferView>& maybeSrc)
+    {
+        const dom::ArrayBufferView* srcView = nullptr;
+        if (!maybeSrc.IsNull()) {
+            srcView = &maybeSrc.Value();
+        }
+        TexImage3D(target, level, internalFormat, width, height, depth, border,
+                   unpackFormat, unpackType, srcView, 0);
+    }
+
+    void TexImage3D(GLenum target, GLint level, GLenum internalFormat, GLsizei width,
+                    GLsizei height, GLsizei depth, GLint border, GLenum unpackFormat,
+                    GLenum unpackType, const dom::ArrayBufferView& srcView,
+                    GLuint srcElemOffset)
+    {
+        TexImage3D(target, level, internalFormat, width, height, depth, border,
+                   unpackFormat, unpackType, &srcView, srcElemOffset);
+    }
+
+    ////
 
     void TexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
                        GLint zOffset, GLsizei width, GLsizei height, GLsizei depth,
                        GLenum unpackFormat, GLenum unpackType,
-                       const dom::ArrayBufferView& data, ErrorResult&);
+                       const dom::ArrayBufferView& srcView, GLuint srcElemOffset,
+                       ErrorResult&);
     void TexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
                        GLint zOffset, GLenum unpackFormat, GLenum unpackType,
                        const dom::ImageData& data, ErrorResult&);
     void TexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
                        GLint zOffset, GLenum unpackFormat, GLenum unpackType,
                        const dom::Element& elem, ErrorResult& out_error);
 
+    ////
+
     void CopyTexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
                            GLint zOffset, GLint x, GLint y, GLsizei width,
                            GLsizei height);
+
+    ////
+
     void CompressedTexImage3D(GLenum target, GLint level, GLenum internalFormat,
-                              GLsizei width, GLsizei height, GLsizei depth,
-                              GLint border, const dom::ArrayBufferView& data);
+                              GLsizei width, GLsizei height, GLsizei depth, GLint border,
+                              const dom::ArrayBufferView& srcView, GLuint srcElemOffset);
     void CompressedTexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
                                  GLint zOffset, GLsizei width, GLsizei height,
                                  GLsizei depth, GLenum sizedUnpackFormat,
-                                 const dom::ArrayBufferView& data);
+                                 const dom::ArrayBufferView& srcView,
+                                 GLuint srcElemOffset);
 
     ////////////////
     // Texture PBOs
 
     void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
                     GLsizei width, GLsizei height, GLint border, GLenum unpackFormat,
                     GLenum unpackType, WebGLsizeiptr offset, ErrorResult&);
 
--- a/dom/canvas/WebGL2ContextTextures.cpp
+++ b/dom/canvas/WebGL2ContextTextures.cpp
@@ -40,48 +40,44 @@ WebGL2Context::TexStorage3D(GLenum rawTe
 
     tex->TexStorage(funcName, target, levels, internalFormat, width, height, depth);
 }
 
 void
 WebGL2Context::TexImage3D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
                           GLsizei width, GLsizei height, GLsizei depth, GLint border,
                           GLenum unpackFormat, GLenum unpackType,
-                          const dom::Nullable<dom::ArrayBufferView>& maybeView)
+                          const dom::ArrayBufferView>* srcView, GLuint srcElemOffset)
 {
     const char funcName[] = "texImage3D";
     const uint8_t funcDims = 3;
 
     TexImageTarget target;
     WebGLTexture* tex;
     if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
                                 &tex))
     {
         return;
     }
 
-    const dom::ArrayBufferView* view = nullptr;
-    if (!maybeView.IsNull()) {
-        view = &maybeView.Value();
-    }
-
     const bool isSubImage = false;
     const GLint xOffset = 0;
     const GLint yOffset = 0;
     const GLint zOffset = 0;
     tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
                        yOffset, zOffset, width, height, depth, border, unpackFormat,
-                       unpackType, view);
+                       unpackType, view, srcElemOffset);
 }
 
 void
 WebGL2Context::TexSubImage3D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
                              GLint yOffset, GLint zOffset, GLsizei width, GLsizei height,
                              GLsizei depth, GLenum unpackFormat, GLenum unpackType,
-                             const dom::ArrayBufferView& view, ErrorResult&)
+                             const dom::ArrayBufferView& srcView, GLuint srcElemOffset,
+                             ErrorResult&)
 {
     const char funcName[] = "texSubImage3D";
     const uint8_t funcDims = 3;
 
     TexImageTarget target;
     WebGLTexture* tex;
     if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
                                 &tex))
@@ -89,17 +85,17 @@ WebGL2Context::TexSubImage3D(GLenum rawT
         return;
     }
 
     const bool isSubImage = true;
     const GLenum internalFormat = 0;
     const GLint border = 0;
     tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
                        yOffset, zOffset, width, height, depth, border, unpackFormat,
-                       unpackType, &view);
+                       unpackType, &srcView, srcElemOffset);
 }
 
 void
 WebGL2Context::TexSubImage3D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
                              GLint yOffset, GLint zOffset, GLenum unpackFormat,
                              GLenum unpackType, const dom::ImageData& imageData,
                              ErrorResult&)
 {
@@ -142,53 +138,55 @@ WebGL2Context::TexSubImage3D(GLenum rawT
     tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
                        yOffset, zOffset, unpackFormat, unpackType, elem, &out_rv);
 }
 
 void
 WebGL2Context::CompressedTexImage3D(GLenum rawTexImageTarget, GLint level,
                                     GLenum internalFormat, GLsizei width, GLsizei height,
                                     GLsizei depth, GLint border,
-                                    const dom::ArrayBufferView& view)
+                                    const dom::ArrayBufferView& srcView,
+                                    GLuint srcElemOffset)
 {
     const char funcName[] = "compressedTexImage3D";
     const uint8_t funcDims = 3;
 
     TexImageTarget target;
     WebGLTexture* tex;
     if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
                                 &tex))
     {
         return;
     }
 
     tex->CompressedTexImage(funcName, target, level, internalFormat, width, height, depth,
-                            border, view);
+                            border, view, srcElemOffset);
 }
 
 void
 WebGL2Context::CompressedTexSubImage3D(GLenum rawTexImageTarget, GLint level,
                                        GLint xOffset, GLint yOffset, GLint zOffset,
                                        GLsizei width, GLsizei height, GLsizei depth,
                                        GLenum sizedUnpackFormat,
-                                       const dom::ArrayBufferView& view)
+                                       const dom::ArrayBufferView& srcView,
+                                       GLuint srcElemOffset)
 {
     const char funcName[] = "compressedTexSubImage3D";
     const uint8_t funcDims = 3;
 
     TexImageTarget target;
     WebGLTexture* tex;
     if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
                                 &tex))
     {
         return;
     }
 
     tex->CompressedTexSubImage(funcName, target, level, xOffset, yOffset, zOffset, width,
-                               height, depth, sizedUnpackFormat, view);
+                               height, depth, sizedUnpackFormat, view, srcElemOffset);
 }
 
 void
 WebGL2Context::CopyTexSubImage3D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
                                  GLint yOffset, GLint zOffset, GLint x, GLint y,
                                  GLsizei width, GLsizei height)
 {
     const char funcName[] = "copyTexSubImage3D";
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -882,17 +882,31 @@ public:
                            GLsizei height);
 
     ////
 
     void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
                     GLsizei width, GLsizei height, GLint border, GLenum unpackFormat,
                     GLenum unpackType,
                     const dom::Nullable<dom::ArrayBufferView>& maybeView,
-                    ErrorResult&);
+                    ErrorResult& out_error)
+    {
+        if (IsContextLost())
+            return;
+
+        TexImage2D(texImageTarget, level, internalFormat, width, height, border,
+                   unpackFormat, unpackType, maybeView, 0, out_error);
+    }
+
+    void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
+                    GLsizei width, GLsizei height, GLint border, GLenum unpackFormat,
+                    GLenum unpackType,
+                    const dom::Nullable<dom::ArrayBufferView>& maybeSrc,
+                    GLuint srcElemOffset, ErrorResult&);
+
 protected:
     void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
                     GLenum unpackFormat, GLenum unpackType,
                     const dom::ImageData& imageData, ErrorResult& out_error);
 public:
     void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
                     GLenum unpackFormat, GLenum unpackType, const dom::Element& elem,
                     ErrorResult& out_error);
@@ -907,58 +921,72 @@ protected:
                        GLenum unpackFormat, GLenum unpackType,
                        const dom::ImageData& imageData, ErrorResult& out_error);
 public:
     void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
                        GLenum unpackFormat, GLenum unpackType, const dom::Element& elem,
                        ErrorResult& out_error);
 
     ////////////////
-    // Pseudo-nullable WebGL1 entrypoints
+    // dom::ImageData
 
     void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
                     GLenum unpackFormat, GLenum unpackType,
                     const dom::ImageData* imageData, ErrorResult& out_error)
     {
         const char funcName[] = "texImage2D";
-        if (!imageData) {
-            ErrorInvalidValue("%s: `data` must not be null.", funcName);
+        if (IsContextLost())
             return;
-        }
+
+        if (!imageData)
+            return ErrorInvalidValue("%s: `data` must not be null.", funcName);
+
         TexImage2D(texImageTarget, level, internalFormat, unpackFormat, unpackType,
                    *imageData, out_error);
     }
 
     void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
-                       GLsizei width, GLsizei height, GLenum unpackFormat,
-                       GLenum unpackType,
-                       const dom::Nullable<dom::ArrayBufferView>& maybeView, ErrorResult&)
-    {
-        const char funcName[] = "texSubImage2D";
-        if (maybeView.IsNull()) {
-            ErrorInvalidValue("%s: `data` must not be null.", funcName);
-            return;
-        }
-        TexSubImage2D(texImageTarget, level, xOffset, yOffset, width, height,
-                      unpackFormat, unpackType, maybeView.Value());
-    }
-
-    void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
                        GLenum unpackFormat, GLenum unpackType,
                        const dom::ImageData* imageData, ErrorResult& out_error)
     {
         const char funcName[] = "texSubImage2D";
         if (!imageData) {
             ErrorInvalidValue("%s: `data` must not be null.", funcName);
             return;
         }
         TexSubImage2D(texImageTarget, level, xOffset, yOffset, unpackFormat, unpackType,
                       *imageData, out_error);
     }
 
+    ////
+    // ArrayBufferView
+
+    void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
+                       GLsizei width, GLsizei height, GLenum unpackFormat,
+                       GLenum unpackType,
+                       const dom::Nullable<dom::ArrayBufferView>& maybeSrc,
+                       ErrorResult& out_error)
+    {
+        const char funcName[] = "texSubImage2D";
+        if (IsContextLost())
+            return;
+
+        if (maybeSrc.IsNull())
+            return ErrorInvalidValue("%s: `data` must not be null.", funcName);
+
+        TexSubImage2D(texImageTarget, level, xOffset, yOffset, width, height,
+                      unpackFormat, unpackType, maybeView.Value(), 0, out_error);
+    }
+
+    void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
+                       GLsizei width, GLsizei height, GLenum unpackFormat,
+                       GLenum unpackType,
+                       const dom::ArrayBufferView& srcView, GLuint srcElemOffset,
+                       ErrorResult&);
+
     //////
     // WebGLTextureUpload.cpp
 public:
     bool ValidateUnpackPixels(const char* funcName, uint32_t fullRows,
                               uint32_t tailPixels, webgl::TexUnpackBlob* blob);
 
 protected:
     bool ValidateTexImageSpecification(const char* funcName, uint8_t funcDims,
--- a/dom/canvas/WebGLTexture.h
+++ b/dom/canvas/WebGLTexture.h
@@ -231,17 +231,17 @@ public:
 
     ////////////////////////////////////
     // WebGLTextureUpload.cpp
 
     void TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarget target,
                        GLint level, GLenum internalFormat, GLint xOffset, GLint yOffset,
                        GLint zOffset, GLsizei width, GLsizei height, GLsizei depth,
                        GLint border, GLenum unpackFormat, GLenum unpackType,
-                       const dom::ArrayBufferView* view);
+                       const dom::ArrayBufferView* srcView, GLuint srcElemOffset);
 
     void TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarget target,
                        GLint level, GLenum internalFormat, GLint xOffset, GLint yOffset,
                        GLint zOffset, GLenum unpackFormat, GLenum unpackType,
                        const dom::ImageData& imageData);
 
     void TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarget target,
                        GLint level, GLenum internalFormat, GLint xOffset, GLint yOffset,
@@ -283,21 +283,21 @@ protected:
                   const webgl::TexUnpackBlob* blob);
     void TexSubImage(const char* funcName, TexImageTarget target, GLint level,
                      GLint xOffset, GLint yOffset, GLint zOffset,
                      const webgl::PackingInfo& pi, const webgl::TexUnpackBlob* blob);
 public:
     void CompressedTexImage(const char* funcName, TexImageTarget target, GLint level,
                             GLenum internalFormat, GLsizei width, GLsizei height,
                             GLsizei depth, GLint border,
-                            const dom::ArrayBufferView& view);
+                            const dom::ArrayBufferView& srcView, GLuint srcElemOffset);
     void CompressedTexSubImage(const char* funcName, TexImageTarget target, GLint level,
                                GLint xOffset, GLint yOffset, GLint zOffset, GLsizei width,
                                GLsizei height, GLsizei depth, GLenum sizedUnpackFormat,
-                               const dom::ArrayBufferView& view);
+                               const dom::ArrayBufferView& srcView, GLuint srcElemOffset);
     void CopyTexImage2D(TexImageTarget target, GLint level, GLenum internalFormat,
                         GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
     void CopyTexSubImage(const char* funcName, TexImageTarget target, GLint level,
                          GLint xOffset, GLint yOffset, GLint zOffset, GLint x, GLint y,
                          GLsizei width, GLsizei height);
 
     ////////////////////////////////////
 
--- a/dom/canvas/WebGLTextureUpload.cpp
+++ b/dom/canvas/WebGLTextureUpload.cpp
@@ -178,17 +178,17 @@ WebGLContext::ValidateUnpackPixels(const
                           funcName, fullRowsNeeded.value(), usedPixelsPerRow.value(),
                           fullRows, tailPixels);
     return false;
 }
 
 static bool
 ValidateUnpackBytes(WebGLContext* webgl, const char* funcName, uint32_t width,
                     uint32_t height, uint32_t depth, const webgl::PackingInfo& pi,
-                    uint32_t byteCount, webgl::TexUnpackBlob* blob)
+                    size_t byteCount, webgl::TexUnpackBlob* blob)
 {
     if (!width || !height || !depth)
         return true;
 
     const auto bytesPerPixel = webgl::BytesPerPixel(pi);
     const auto bytesPerRow = CheckedUint32(blob->mRowLength) * bytesPerPixel;
     const auto rowStride = RoundUpToMultipleOf(bytesPerRow, blob->mAlignment);
 
@@ -235,46 +235,48 @@ WebGLContext::ValidateUnpackInfo(const c
 }
 
 void
 WebGLTexture::TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarget target,
                             GLint level, GLenum internalFormat, GLint xOffset,
                             GLint yOffset, GLint zOffset, GLsizei rawWidth,
                             GLsizei rawHeight, GLsizei rawDepth, GLint border,
                             GLenum unpackFormat, GLenum unpackType,
-                            const dom::ArrayBufferView* view)
+                            const dom::ArrayBufferView* srcView, GLuint srcElemOffset)
 {
     uint32_t width, height, depth;
     if (!ValidateExtents(mContext, funcName, rawWidth, rawHeight, rawDepth, border,
                          &width, &height, &depth))
     {
         return;
     }
 
     const bool usePBOs = false;
     webgl::PackingInfo pi;
     if (!mContext->ValidateUnpackInfo(funcName, usePBOs, unpackFormat, unpackType, &pi))
         return;
 
     ////
 
     const uint8_t* bytes = nullptr;
-    uint32_t byteCount = 0;
+    size_t byteCount = 0;
 
-    if (view) {
-        view->ComputeLengthAndData();
-        bytes = view->DataAllowShared();
-        byteCount = view->LengthAllowShared();
-
-        const auto& jsType = view->Type();
+    if (srcView) {
+        const auto& jsType = srcView->Type();
         if (!DoesJSTypeMatchUnpackType(pi.type, jsType)) {
             mContext->ErrorInvalidOperation("%s: `pixels` not compatible with `type`.",
                                             funcName);
             return;
         }
+
+        if (!mContext->ValidateArrayBufferView(funcName, *srcView, srcElemOffset, 0,
+                                               &bytes, &byteCount))
+        {
+            return;
+        }
     } else if (isSubImage) {
         mContext->ErrorInvalidValue("%s: `pixels` must not be null.", funcName);
         return;
     }
 
     const bool isClientData = true;
     webgl::TexUnpackBytes blob(mContext, target, width, height, depth, isClientData,
                                bytes);
@@ -1446,17 +1448,18 @@ WebGLTexture::TexSubImage(const char* fu
 
 ////////////////////////////////////////
 // CompressedTex(Sub)Image
 
 void
 WebGLTexture::CompressedTexImage(const char* funcName, TexImageTarget target, GLint level,
                                  GLenum internalFormat, GLsizei rawWidth,
                                  GLsizei rawHeight, GLsizei rawDepth, GLint border,
-                                 const dom::ArrayBufferView& view)
+                                 const dom::ArrayBufferView& srcView,
+                                 GLuint srcElemOffset)
 {
     uint32_t width, height, depth;
     if (!ValidateExtents(mContext, funcName, rawWidth, rawHeight, rawDepth, border,
                          &width, &height, &depth))
     {
         return;
     }
 
@@ -1486,22 +1489,26 @@ WebGLTexture::CompressedTexImage(const c
     }
 
     if (!ValidateTargetForFormat(funcName, mContext, target, format))
         return;
 
     ////////////////////////////////////
     // Get source info
 
-    view.ComputeLengthAndData();
-    const void* data = view.DataAllowShared();
-    size_t dataSize = view.LengthAllowShared();
+    uint8_t* bytes;
+    size_t byteLen;
+    if (!mContext->ValidateArrayBufferView(funcName, srcView, srcElemOffset, 0, &bytes,
+                                           &byteLen))
+    {
+        return;
+    }
 
     if (!ValidateCompressedTexUnpack(mContext, funcName, width, height, depth, format,
-                                     dataSize))
+                                     byteLen))
     {
         return;
     }
 
     ////////////////////////////////////
     // Check that source is compatible with dest
 
     if (!ValidateCompressedTexImageRestrictions(funcName, mContext, target, level, format,
@@ -1512,17 +1519,17 @@ WebGLTexture::CompressedTexImage(const c
 
     ////////////////////////////////////
     // Do the thing!
 
     mContext->gl->MakeCurrent();
 
     // Warning: Possibly shared memory.  See bug 1225033.
     GLenum error = DoCompressedTexImage(mContext->gl, target, level, internalFormat,
-                                        width, height, depth, dataSize, data);
+                                        width, height, depth, byteLen, bytes);
     if (error == LOCAL_GL_OUT_OF_MEMORY) {
         mContext->ErrorOutOfMemory("%s: Ran out of memory during upload.", funcName);
         return;
     }
     if (error) {
         MOZ_RELEASE_ASSERT(false, "GFX: We should have caught all other errors.");
         mContext->GenerateWarning("%s: Unexpected error during texture upload. Context"
                                   " lost.",
@@ -1559,17 +1566,18 @@ IsSubImageBlockAligned(const webgl::Comp
     return true;
 }
 
 void
 WebGLTexture::CompressedTexSubImage(const char* funcName, TexImageTarget target,
                                     GLint level, GLint xOffset, GLint yOffset,
                                     GLint zOffset, GLsizei rawWidth, GLsizei rawHeight,
                                     GLsizei rawDepth, GLenum sizedUnpackFormat,
-                                    const dom::ArrayBufferView& view)
+                                    const dom::ArrayBufferView& srcView,
+                                    GLuint srcElemOffset)
 {
     uint32_t width, height, depth;
     if (!ValidateExtents(mContext, funcName, rawWidth, rawHeight, rawDepth, 0, &width,
                          &height, &depth))
     {
         return;
     }
 
@@ -1585,19 +1593,23 @@ WebGLTexture::CompressedTexSubImage(cons
     MOZ_ASSERT(imageInfo);
 
     auto dstUsage = imageInfo->mFormat;
     auto dstFormat = dstUsage->format;
 
     ////////////////////////////////////
     // Get source info
 
-    view.ComputeLengthAndData();
-    size_t dataSize = view.LengthAllowShared();
-    const void* data = view.DataAllowShared();
+    uint8_t* bytes;
+    size_t byteLen;
+    if (!mContext->ValidateArrayBufferView(funcName, srcView, srcElemOffset, 0, &bytes,
+                                           &byteLen))
+    {
+        return;
+    }
 
     auto srcUsage = mContext->mFormatUsage->GetSizedTexUsage(sizedUnpackFormat);
     if (!srcUsage->format->compression) {
         mContext->ErrorInvalidEnum("%s: Specified format must be compressed.", funcName);
         return;
     }
 
     if (srcUsage != dstUsage) {
@@ -1605,17 +1617,17 @@ WebGLTexture::CompressedTexSubImage(cons
                                         " existing texture image.",
                                         funcName);
         return;
     }
 
     auto format = srcUsage->format;
     MOZ_ASSERT(format == dstFormat);
     if (!ValidateCompressedTexUnpack(mContext, funcName, width, height, depth, format,
-                                     dataSize))
+                                     byteLen))
     {
         return;
     }
 
     ////////////////////////////////////
     // Check that source is compatible with dest
 
     switch (format->compression->family) {
@@ -1664,17 +1676,17 @@ WebGLTexture::CompressedTexSubImage(cons
                                              imageInfo, &uploadWillInitialize))
     {
         return;
     }
 
     // Warning: Possibly shared memory.  See bug 1225033.
     GLenum error = DoCompressedTexSubImage(mContext->gl, target, level, xOffset, yOffset,
                                            zOffset, width, height, depth,
-                                           sizedUnpackFormat, dataSize, data);
+                                           sizedUnpackFormat, byteLen, bytes);
     if (error == LOCAL_GL_OUT_OF_MEMORY) {
         mContext->ErrorOutOfMemory("%s: Ran out of memory during upload.", funcName);
         return;
     }
     if (error) {
         MOZ_RELEASE_ASSERT(false, "GFX: We should have caught all other errors.");
         mContext->GenerateWarning("%s: Unexpected error during texture upload. Context"
                                   " lost.",