--- a/dom/canvas/TexUnpackBlob.cpp
+++ b/dom/canvas/TexUnpackBlob.cpp
@@ -16,30 +16,28 @@
#include "WebGLTexelConversions.h"
#include "WebGLTexture.h"
namespace mozilla {
namespace webgl {
TexUnpackBlob::TexUnpackBlob(const WebGLContext* webgl, uint32_t alignment,
uint32_t rowLength, uint32_t imageHeight, uint32_t width,
- uint32_t height, uint32_t depth, bool hasData)
+ uint32_t height, uint32_t depth)
: mAlignment(alignment)
, mRowLength(rowLength)
, mImageHeight(imageHeight)
, mSkipPixels(webgl->mPixelStore_UnpackSkipPixels)
, mSkipRows(webgl->mPixelStore_UnpackSkipRows)
, mSkipImages(webgl->mPixelStore_UnpackSkipImages)
, mWidth(width)
, mHeight(height)
, mDepth(depth)
-
- , mHasData(hasData)
{ }
static GLenum
DoTexOrSubImage(bool isSubImage, gl::GLContext* gl, TexImageTarget target, GLint level,
const DriverUnpackInfo* dui, GLint xOffset, GLint yOffset, GLint zOffset,
GLsizei width, GLsizei height, GLsizei depth, const void* data)
{
if (isSubImage) {
@@ -68,22 +66,23 @@ TexUnpackBlob::OriginsForDOM(WebGLContex
static uint32_t
FallbackOnZero(uint32_t val, uint32_t fallback)
{
return (val ? val : fallback);
}
TexUnpackBytes::TexUnpackBytes(const WebGLContext* webgl, uint32_t width, uint32_t height,
- uint32_t depth, const void* bytes)
+ uint32_t depth, bool isClientData, const void* ptr)
: TexUnpackBlob(webgl, webgl->mPixelStore_UnpackAlignment,
FallbackOnZero(webgl->mPixelStore_UnpackRowLength, width),
FallbackOnZero(webgl->mPixelStore_UnpackImageHeight, height),
- width, height, depth, bool(bytes))
- , mBytes(bytes)
+ width, height, depth)
+ , mIsClientData(isClientData)
+ , mPtr(ptr)
{ }
static bool
UnpackFormatHasAlpha(GLenum unpackFormat)
{
switch (unpackFormat) {
case LOCAL_GL_ALPHA:
case LOCAL_GL_LUMINANCE_ALPHA:
@@ -146,26 +145,30 @@ bool
TexUnpackBytes::TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
WebGLTexture* tex, TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLint xOffset,
GLint yOffset, GLint zOffset, GLenum* const out_error) const
{
WebGLContext* webgl = tex->mContext;
gl::GLContext* gl = webgl->gl;
- const void* uploadBytes = mBytes;
+ const void* uploadPtr = mPtr;
UniqueBuffer tempBuffer;
do {
- if (!mBytes || !mWidth || !mHeight || !mDepth)
+ if (!mWidth || !mHeight || !mDepth)
break;
if (webgl->IsWebGL2())
break;
MOZ_ASSERT(mDepth == 1);
+ MOZ_ASSERT(mIsClientData);
+
+ if (!mPtr)
+ break;
const webgl::PackingInfo pi = { dui->unpackFormat, dui->unpackType };
const bool needsYFlip = webgl->mPixelStore_FlipY;
bool needsAlphaPremult = webgl->mPixelStore_PremultiplyAlpha;
if (!UnpackFormatHasAlpha(pi.format))
needsAlphaPremult = false;
@@ -216,28 +219,28 @@ TexUnpackBytes::TexOrSubImage(bool isSub
webgl->ErrorOutOfMemory("%s: OOM during FLIP_Y/PREMULTIPLY_ALPHA handling.",
funcName);
return false;
}
if (!needsAlphaPremult) {
MOZ_ASSERT(needsYFlip);
- const uint8_t* src = (const uint8_t*)mBytes;
+ const uint8_t* src = (const uint8_t*)mPtr;
const uint8_t* const srcEnd = src + rowStride.value() * mHeight;
uint8_t* dst = (uint8_t*)tempBuffer.get() + rowStride.value() * (mHeight - 1);
while (src != srcEnd) {
memcpy(dst, src, bytesPerRow.value());
src += rowStride.value();
dst -= rowStride.value();
}
- uploadBytes = tempBuffer.get();
+ uploadPtr = tempBuffer.get();
break;
}
const auto texelFormat = FormatFromPacking(pi);
if (texelFormat == WebGLTexelFormat::FormatNotSupportingAnyConversion) {
MOZ_ASSERT(false, "Bad texelFormat from pi.");
webgl->ErrorOutOfMemory("%s: FormatFromPacking failed during"
" PREMULTIPLY_ALPHA handling.",
@@ -251,45 +254,44 @@ TexUnpackBytes::TexOrSubImage(bool isSub
const bool srcPremultiplied = false;
const bool dstPremultiplied = needsAlphaPremult; // Always true here.
// And go!:
MOZ_ASSERT(srcOrigin != dstOrigin || srcPremultiplied != dstPremultiplied);
bool unused_wasTrivial;
if (!ConvertImage(mWidth, mHeight,
- mBytes, rowStride.value(), srcOrigin, texelFormat,
+ mPtr, rowStride.value(), srcOrigin, texelFormat,
srcPremultiplied,
tempBuffer.get(), rowStride.value(), dstOrigin, texelFormat,
dstPremultiplied, &unused_wasTrivial))
{
MOZ_ASSERT(false, "ConvertImage failed unexpectedly.");
webgl->ErrorOutOfMemory("%s: ConvertImage failed during PREMULTIPLY_ALPHA"
" handling.",
funcName);
return false;
}
- uploadBytes = tempBuffer.get();
+ uploadPtr = tempBuffer.get();
} while (false);
*out_error = DoTexOrSubImage(isSubImage, gl, target, level, dui, xOffset, yOffset,
- zOffset, mWidth, mHeight, mDepth, uploadBytes);
+ zOffset, mWidth, mHeight, mDepth, uploadPtr);
return true;
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// TexUnpackImage
TexUnpackImage::TexUnpackImage(const WebGLContext* webgl, uint32_t imageHeight,
uint32_t width, uint32_t height, uint32_t depth,
const RefPtr<layers::Image>& image, bool isAlphaPremult)
- : TexUnpackBlob(webgl, 0, image->GetSize().width, imageHeight, width, height, depth,
- true)
+ : TexUnpackBlob(webgl, 0, image->GetSize().width, imageHeight, width, height, depth)
, mImage(image)
, mIsAlphaPremult(isAlphaPremult)
{ }
bool
TexUnpackImage::TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
WebGLTexture* tex, TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLint xOffset,
@@ -369,18 +371,17 @@ TexUnpackImage::TexOrSubImage(bool isSub
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// TexUnpackSurface
TexUnpackSurface::TexUnpackSurface(const WebGLContext* webgl, uint32_t imageHeight,
uint32_t width, uint32_t height, uint32_t depth,
gfx::SourceSurface* surf, bool isAlphaPremult)
- : TexUnpackBlob(webgl, 0, surf->GetSize().width, imageHeight, width, height, depth,
- true)
+ : TexUnpackBlob(webgl, 0, surf->GetSize().width, imageHeight, width, height, depth)
, mSurf(surf)
, mIsAlphaPremult(isAlphaPremult)
{ }
//////////
static bool
GuessAlignment(const void* data, size_t bytesPerRow, size_t stride, size_t maxAlignment,
--- a/dom/canvas/TexUnpackBlob.h
+++ b/dom/canvas/TexUnpackBlob.h
@@ -51,81 +51,89 @@ public:
const uint32_t mRowLength;
const uint32_t mImageHeight;
const uint32_t mSkipPixels;
const uint32_t mSkipRows;
const uint32_t mSkipImages;
const uint32_t mWidth;
const uint32_t mHeight;
const uint32_t mDepth;
- const bool mHasData;
protected:
TexUnpackBlob(const WebGLContext* webgl, uint32_t alignment, uint32_t rowLength,
- uint32_t imageHeight, uint32_t width, uint32_t height, uint32_t depth,
- bool hasData);
+ uint32_t imageHeight, uint32_t width, uint32_t height, uint32_t depth);
public:
+ virtual bool HasData() const { return true; }
+
virtual bool TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
WebGLTexture* tex, TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLint xOffset,
GLint yOffset, GLint zOffset,
GLenum* const out_error) const = 0;
static void OriginsForDOM(WebGLContext* webgl, gl::OriginPos* const out_src,
gl::OriginPos* const out_dst);
};
class TexUnpackBytes : public TexUnpackBlob
{
public:
- const void* const mBytes;
+ const bool mIsClientData;
+ const void* const mPtr;
TexUnpackBytes(const WebGLContext* webgl, uint32_t width, uint32_t height,
- uint32_t depth, const void* bytes);
+ uint32_t depth, bool isClientData, const void* ptr);
+
+ virtual bool HasData() const override {
+ if (mIsClientData && !mPtr)
+ return false;
+
+ return true;
+ }
virtual bool TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
- WebGLTexture* tex, TexImageTarget target, GLint level,
- const webgl::DriverUnpackInfo* dui, GLint xOffset,
- GLint yOffset, GLint zOffset,
- GLenum* const out_error) const override;
+ WebGLTexture* tex, TexImageTarget target, GLint level,
+ const webgl::DriverUnpackInfo* dui, GLint xOffset,
+ GLint yOffset, GLint zOffset,
+ GLenum* const out_error) const override;
};
class TexUnpackImage : public TexUnpackBlob
{
public:
const RefPtr<layers::Image> mImage;
const bool mIsAlphaPremult;
TexUnpackImage(const WebGLContext* webgl, uint32_t imageHeight, uint32_t width,
uint32_t height, uint32_t depth, const RefPtr<layers::Image>& image,
bool isAlphaPremult);
virtual bool TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
- WebGLTexture* tex, TexImageTarget target, GLint level,
- const webgl::DriverUnpackInfo* dui, GLint xOffset,
- GLint yOffset, GLint zOffset,
- GLenum* const out_error) const override;
+ WebGLTexture* tex, TexImageTarget target, GLint level,
+ const webgl::DriverUnpackInfo* dui, GLint xOffset,
+ GLint yOffset, GLint zOffset,
+ GLenum* const out_error) const override;
};
class TexUnpackSurface : public TexUnpackBlob
{
public:
const RefPtr<gfx::SourceSurface> mSurf;
const bool mIsAlphaPremult;
TexUnpackSurface(const WebGLContext* webgl, uint32_t imageHeight, uint32_t width,
uint32_t height, uint32_t depth, gfx::SourceSurface* surf,
bool isAlphaPremult);
virtual bool TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
- WebGLTexture* tex, TexImageTarget target, GLint level,
- const webgl::DriverUnpackInfo* dui, GLint xOffset,
- GLint yOffset, GLint zOffset,
- GLenum* const out_error) const override;
+ WebGLTexture* tex, TexImageTarget target, GLint level,
+ const webgl::DriverUnpackInfo* dui, GLint xOffset,
+ GLint yOffset, GLint zOffset,
+ GLenum* const out_error) const override;
protected:
static bool ConvertSurface(WebGLContext* webgl, const webgl::DriverUnpackInfo* dui,
gfx::DataSourceSurface* surf, bool isSurfAlphaPremult,
UniqueBuffer* const out_convertedBuffer,
uint8_t* const out_convertedAlignment,
bool* const out_wasTrivial, bool* const out_outOfMemory);
static bool UploadDataSurface(bool isSubImage, WebGLContext* webgl,
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -937,20 +937,16 @@ public:
GLenum unpackFormat, GLenum unpackType, T& elem, ErrorResult& out_error)
{
TexSubImage2D(texImageTarget, level, xOffset, yOffset, unpackFormat, unpackType,
&elem, &out_error);
}
//////
// WebGLTextureUpload.cpp
-public:
- bool ValidateUnpackPixels(const char* funcName, uint32_t fullRows,
- uint32_t tailPixels, const webgl::TexUnpackBlob* blob);
-
protected:
bool ValidateTexImageSpecification(const char* funcName, uint8_t funcDims,
GLenum texImageTarget, GLint level,
GLsizei width, GLsizei height, GLsizei depth,
GLint border,
TexImageTarget* const out_target,
WebGLTexture** const out_texture,
WebGLTexture::ImageInfo** const out_imageInfo);
@@ -961,18 +957,18 @@ protected:
TexImageTarget* const out_target,
WebGLTexture** const out_texture,
WebGLTexture::ImageInfo** const out_imageInfo);
bool GetUnpackValuesForImage(const char* funcName, uint32_t srcImageWidth,
uint32_t srcImageHeight, uint32_t* const out_rowLength,
uint32_t* const out_imageHeight);
- bool ValidateUnpackInfo(const char* funcName, GLenum format, GLenum type,
- webgl::PackingInfo* const out);
+ bool ValidateUnpackInfo(const char* funcName, bool usePBOs, GLenum format,
+ GLenum type, webgl::PackingInfo* const out);
// -----------------------------------------------------------------------------
// Vertices Feature (WebGLContextVertices.cpp)
public:
void DrawArrays(GLenum mode, GLint first, GLsizei count);
void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count,
GLsizei primcount);
void DrawElements(GLenum mode, GLsizei count, GLenum type,
--- a/dom/canvas/WebGLTexture.h
+++ b/dom/canvas/WebGLTexture.h
@@ -220,16 +220,21 @@ 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::Nullable<dom::ArrayBufferView>& maybeView);
+ void 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, WebGLsizeiptr offset);
void TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarget target,
GLint level, GLenum internalFormat, GLint xOffset, GLint yOffset,
GLint zOffset, GLenum unpackFormat, GLenum unpackType,
dom::ImageData* imageData);
void TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarget target,
GLint level, GLenum internalFormat, GLint xOffset, GLint yOffset,
--- a/dom/canvas/WebGLTextureUpload.cpp
+++ b/dom/canvas/WebGLTextureUpload.cpp
@@ -77,20 +77,117 @@ ValidateExtents(WebGLContext* webgl, con
}
*out_width = width;
*out_height = height;
*out_depth = depth;
return true;
}
+static bool
+ValidateUnpackPixels(WebGLContext* webgl, const char* funcName, uint32_t fullRows,
+ uint32_t tailPixels, const webgl::TexUnpackBlob* blob)
+{
+ const auto usedPixelsPerRow = CheckedUint32(blob->mSkipPixels) + blob->mWidth;
+ const auto usedRowsPerImage = CheckedUint32(blob->mSkipRows) + blob->mHeight;
+ const auto usedImages = CheckedUint32(blob->mSkipImages) + blob->mDepth;
+
+ bool unpackVarsValid = false;
+ if (!usedPixelsPerRow.isValid() ||
+ !usedRowsPerImage.isValid() ||
+ !usedImages.isValid())
+ {
+ webgl->ErrorOutOfMemory("%s: Invalid calculation for e.g. UNPACK_SKIP_PIXELS +"
+ " width.",
+ funcName);
+ return false;
+ }
+
+ //////
+
+ if (usedPixelsPerRow.value() > blob->mRowLength ||
+ usedRowsPerImage.value() > blob->mImageHeight)
+ {
+ webgl->ErrorInvalidOperation("%s: UNPACK_ROW_LENGTH or UNPACK_IMAGE_HEIGHT too"
+ " small.",
+ funcName);
+ return false;
+ }
+
+ //////
+
+ auto fullRowsNeeded = (usedImages - 1) * blob->mImageHeight;
+ fullRowsNeeded += usedRowsPerImage - 1;
+
+ if (!fullRowsNeeded.isValid()) {
+ webgl->ErrorOutOfMemory("%s: Invalid calculation for required row count.",
+ funcName);
+ return false;
+ }
+
+ if (fullRows > fullRowsNeeded.value())
+ return true;
+
+ if (fullRows == fullRowsNeeded.value() && tailPixels >= usedPixelsPerRow.value())
+ return true;
+
+ webgl->ErrorInvalidOperation("%s: Desired upload requires more data than is"
+ " available: (%u rows plus %u pixels needed, %u rows"
+ " plus %u pixels available)",
+ 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, const webgl::TexUnpackBlob* blob)
+{
+ const auto bytesPerPixel = webgl::BytesPerPixel(pi);
+ const auto bytesPerRow = CheckedUint32(blob->mRowLength) * bytesPerPixel;
+ const auto rowStride = RoundUpToMultipleOf(bytesPerRow, blob->mAlignment);
+
+ const auto fullRows = byteCount / rowStride;
+ if (!fullRows.isValid()) {
+ webgl->ErrorOutOfMemory("%s: Unacceptable upload size calculated.");
+ return nullptr;
+ }
+
+ const auto bodyBytes = fullRows.value() * rowStride.value();
+ const auto tailPixels = (byteCount - bodyBytes) / bytesPerPixel;
+
+ return ValidateUnpackPixels(webgl, funcName, fullRows.value(), tailPixels, blob);
+}
+
+bool
+WebGLContext::ValidateUnpackInfo(const char* funcName, bool usePBOs, GLenum format,
+ GLenum type, webgl::PackingInfo* const out)
+{
+ if (usePBOs != bool(mBoundPixelUnpackBuffer)) {
+ ErrorInvalidOperation("%s: PACK_BUFFER must be %s.", funcName,
+ (usePBOs ? "non-null" : "null"));
+ return false;
+ }
+
+ if (!mFormatUsage->AreUnpackEnumsValid(format, type)) {
+ ErrorInvalidEnum("%s: Invalid unpack format/type: 0x%04x/0x%04x", funcName,
+ format, type);
+ return false;
+ }
+
+ out->format = format;
+ out->type = type;
+ return true;
+}
+
////////////////////////////////////////
// ArrayBufferView?
-static inline bool
+static bool
DoesJSTypeMatchUnpackType(GLenum unpackType, js::Scalar::Type jsType)
{
switch (unpackType) {
case LOCAL_GL_BYTE:
return jsType == js::Scalar::Type::Int8;
case LOCAL_GL_UNSIGNED_BYTE:
return jsType == js::Scalar::Type::Uint8 ||
@@ -120,167 +217,127 @@ DoesJSTypeMatchUnpackType(GLenum unpackT
case LOCAL_GL_FLOAT:
return jsType == js::Scalar::Type::Float32;
default:
return false;
}
}
-bool
-WebGLContext::ValidateUnpackPixels(const char* funcName, uint32_t fullRows,
- uint32_t tailPixels, const webgl::TexUnpackBlob* blob)
+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::Nullable<dom::ArrayBufferView>& maybeView)
{
- const auto usedPixelsPerRow = CheckedUint32(blob->mSkipPixels) + blob->mWidth;
- const auto usedRowsPerImage = CheckedUint32(blob->mSkipRows) + blob->mHeight;
- const auto usedImages = CheckedUint32(blob->mSkipImages) + blob->mDepth;
+ const bool usePBOs = false;
+ webgl::PackingInfo pi;
+ if (!mContext->ValidateUnpackInfo(funcName, usePBOs, unpackFormat, unpackType, &pi))
+ return;
- bool unpackVarsValid = false;
- if (!usedPixelsPerRow.isValid() ||
- !usedRowsPerImage.isValid() ||
- !usedImages.isValid())
+ uint32_t width, height, depth;
+ if (!ValidateExtents(mContext, funcName, rawWidth, rawHeight, rawDepth, border,
+ &width, &height, &depth))
{
- ErrorOutOfMemory("%s: Invalid calculation for e.g. UNPACK_SKIP_PIXELS + width.",
- funcName);
- return false;
+ return;
}
//////
- if (usedPixelsPerRow.value() > blob->mRowLength ||
- usedRowsPerImage.value() > blob->mImageHeight)
- {
- ErrorInvalidOperation("%s: UNPACK_ROW_LENGTH or UNPACK_IMAGE_HEIGHT too small.",
- funcName);
- return false;
- }
-
- //////
-
- auto fullRowsNeeded = (usedImages - 1) * blob->mImageHeight;
- fullRowsNeeded += usedRowsPerImage - 1;
-
- if (!fullRowsNeeded.isValid()) {
- ErrorOutOfMemory("%s: Invalid calculation for required row count.",
- funcName);
- return false;
- }
-
- if (fullRows > fullRowsNeeded.value())
- return true;
-
- if (fullRows == fullRowsNeeded.value() && tailPixels >= usedPixelsPerRow.value())
- return true;
-
- ErrorInvalidOperation("%s: Desired upload requires more data than is available: (%u"
- " rows plus %u pixels needed, %u rows plus %u pixels"
- " available)",
- funcName, fullRowsNeeded.value(), usedPixelsPerRow.value(),
- fullRows, tailPixels);
- return false;
-}
-
-static UniquePtr<webgl::TexUnpackBlob>
-BlobFromView(WebGLContext* webgl, const char* funcName, uint32_t width, uint32_t height,
- uint32_t depth, const webgl::PackingInfo& pi,
- const dom::Nullable<dom::ArrayBufferView>& maybeView)
-{
const void* bytes = nullptr;
uint32_t byteCount = 0;
if (!maybeView.IsNull()) {
const auto& view = maybeView.Value();
const auto jsType = JS_GetArrayBufferViewType(view.Obj());
if (!DoesJSTypeMatchUnpackType(pi.type, jsType)) {
- webgl->ErrorInvalidOperation("%s: `pixels` must be compatible with `type`.",
- funcName);
- return nullptr;
+ mContext->ErrorInvalidOperation("%s: `pixels` must be compatible with"
+ " `type`.",
+ funcName);
+ return;
}
if (width && height && depth) {
view.ComputeLengthAndData();
bytes = view.DataAllowShared();
byteCount = view.LengthAllowShared();
}
}
- UniquePtr<webgl::TexUnpackBlob> blob(new webgl::TexUnpackBytes(webgl, width, height,
- depth, bytes));
+ const bool isClientData = true;
+ const webgl::TexUnpackBytes blob(mContext, width, height, depth, isClientData, bytes);
//////
- if (bytes) {
- const auto bytesPerPixel = webgl::BytesPerPixel(pi);
- const auto bytesPerRow = CheckedUint32(blob->mRowLength) * bytesPerPixel;
- const auto rowStride = RoundUpToMultipleOf(bytesPerRow, blob->mAlignment);
-
- const auto fullRows = byteCount / rowStride;
- if (!fullRows.isValid()) {
- webgl->ErrorOutOfMemory("%s: Unacceptable upload size calculated.");
- return nullptr;
- }
-
- const auto bodyBytes = fullRows.value() * rowStride.value();
- const auto tailPixels = (byteCount - bodyBytes) / bytesPerPixel;
-
- if (!webgl->ValidateUnpackPixels(funcName, fullRows.value(), tailPixels,
- blob.get()))
- {
- return nullptr;
- }
+ if (bytes && !ValidateUnpackBytes(mContext, funcName, width, height, depth, pi,
+ byteCount, &blob))
+ {
+ return;
}
- //////
-
- return Move(blob);
+ TexOrSubImageBlob(isSubImage, funcName, target, level, internalFormat, xOffset,
+ yOffset, zOffset, pi, &blob);
}
-bool
-WebGLContext::ValidateUnpackInfo(const char* funcName, GLenum format, GLenum type,
- webgl::PackingInfo* const out)
-{
- if (!mFormatUsage->AreUnpackEnumsValid(format, type)) {
- ErrorInvalidEnum("%s: Invalid unpack format/type: 0x%04x/0x%04x", funcName,
- format, type);
- return false;
- }
-
- out->format = format;
- out->type = type;
- return true;
-}
+////////////////////////////////////////
+// GLintptr offset
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::Nullable<dom::ArrayBufferView>& maybeView)
+ WebGLsizeiptr offset)
{
+ const bool usePBOs = true;
+ webgl::PackingInfo pi;
+ if (!mContext->ValidateUnpackInfo(funcName, usePBOs, unpackFormat, unpackType, &pi))
+ return;
+
uint32_t width, height, depth;
if (!ValidateExtents(mContext, funcName, rawWidth, rawHeight, rawDepth, border,
&width, &height, &depth))
{
return;
}
- webgl::PackingInfo pi;
- if (!mContext->ValidateUnpackInfo(funcName, unpackFormat, unpackType, &pi))
+ //////
+
+ if (offset < 0) {
+ mContext->ErrorInvalidValue("%s: offset cannot be negative.", funcName);
return;
+ }
+
+ const bool isClientData = false;
+ const void* ptr = (const void*)offset;
+ const webgl::TexUnpackBytes blob(mContext, width, height, depth, isClientData, ptr);
+
+ //////
- const auto blob = BlobFromView(mContext, funcName, width, height, depth, pi,
- maybeView);
- if (!blob)
+ const auto& packBuffer = mContext->mBoundPixelUnpackBuffer;
+ const auto bufferByteCount = packBuffer->ByteLength();
+
+ uint32_t byteCount = 0;
+ if (bufferByteCount >= offset) {
+ byteCount = bufferByteCount - offset;
+ }
+
+ if (!ValidateUnpackBytes(mContext, funcName, width, height, depth, pi, byteCount,
+ &blob))
+ {
return;
+ }
TexOrSubImageBlob(isSubImage, funcName, target, level, internalFormat, xOffset,
- yOffset, zOffset, pi, blob.get());
+ yOffset, zOffset, pi, &blob);
}
////////////////////////////////////////
// ImageData
static already_AddRefed<gfx::SourceSurface>
FromImageData(WebGLContext* webgl, const char* funcName, GLenum unpackType,
dom::ImageData* imageData, dom::Uint8ClampedArray* scopedArr)
@@ -343,18 +400,19 @@ WebGLContext::GetUnpackValuesForImage(co
}
void
WebGLTexture::TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarget target,
GLint level, GLenum internalFormat, GLint xOffset,
GLint yOffset, GLint zOffset, GLenum unpackFormat,
GLenum unpackType, dom::ImageData* imageData)
{
+ const bool usePBOs = false;
webgl::PackingInfo pi;
- if (mContext->ValidateUnpackInfo(funcName, unpackFormat, unpackType, &pi))
+ if (!mContext->ValidateUnpackInfo(funcName, usePBOs, unpackFormat, unpackType, &pi))
return;
if (!imageData) {
// Spec says to generate an INVALID_VALUE error
mContext->ErrorInvalidValue("%s: Null ImageData.", funcName);
return;
}
@@ -383,35 +441,36 @@ WebGLTexture::TexOrSubImage(bool isSubIm
// non-premultiplied alpha values."
const bool surfIsAlphaPremult = false;
const webgl::TexUnpackSurface blob(mContext, imageHeight, width, height, depth, surf,
surfIsAlphaPremult);
const uint32_t fullRows = imageData->Height();
const uint32_t tailPixels = 0;
- if (!mContext->ValidateUnpackPixels(funcName, fullRows, tailPixels, &blob))
+ if (!ValidateUnpackPixels(mContext, funcName, fullRows, tailPixels, &blob))
return;
TexOrSubImageBlob(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, pi, &blob);
}
////////////////////////////////////////
// dom::Element
void
WebGLTexture::TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarget target,
GLint level, GLenum internalFormat, GLint xOffset,
GLint yOffset, GLint zOffset, GLenum unpackFormat,
GLenum unpackType, dom::Element* elem,
ErrorResult* const out_error)
{
+ const bool usePBOs = false;
webgl::PackingInfo pi;
- if (mContext->ValidateUnpackInfo(funcName, unpackFormat, unpackType, &pi))
+ if (!mContext->ValidateUnpackInfo(funcName, usePBOs, unpackFormat, unpackType, &pi))
return;
auto sfer = mContext->SurfaceFromElement(elem);
uint32_t elemWidth = 0;
uint32_t elemHeight = 0;
layers::Image* layersImage = nullptr;
if (!gfxPrefs::WebGLDisableDOMBlitUploads() && sfer.mLayersImage) {
@@ -432,17 +491,19 @@ WebGLTexture::TexOrSubImage(bool isSubIm
const uint32_t height = elemHeight;
const uint32_t depth = 1;
const GLint border = 0;
// While it's counter-intuitive, the shape of the SFEResult API means that we should
// try to pull out a surface first, and then, if we do pull out a surface, check
// CORS/write-only/etc..
if (!layersImage && !surf) {
- webgl::TexUnpackBytes blob(mContext, width, height, depth, nullptr);
+ const bool isClientData = true;
+ const webgl::TexUnpackBytes blob(mContext, width, height, depth, isClientData,
+ nullptr);
TexOrSubImageBlob(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, pi, &blob);
return;
}
//////
if (!sfer.mCORSUsed) {
@@ -487,17 +548,17 @@ WebGLTexture::TexOrSubImage(bool isSubIm
} else {
MOZ_ASSERT(surf);
blob.reset(new webgl::TexUnpackSurface(mContext, imageHeight, width, height,
depth, surf, isAlphaPremult));
}
const uint32_t fullRows = elemHeight;
const uint32_t tailPixels = 0;
- if (!mContext->ValidateUnpackPixels(funcName, fullRows, tailPixels, blob.get()))
+ if (!ValidateUnpackPixels(mContext, funcName, fullRows, tailPixels, blob.get()))
return;
TexOrSubImageBlob(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, pi, blob.get());
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -1260,19 +1321,20 @@ WebGLTexture::TexImage(const char* funcN
////////////////////////////////////
// Check that source and dest info are compatible
auto dstFormat = dstUsage->format;
if (!ValidateTargetForFormat(funcName, mContext, target, dstFormat))
return;
+ const bool hasData = blob->HasData();
if (!mContext->IsWebGL2() && dstFormat->hasDepth) {
if (target != LOCAL_GL_TEXTURE_2D ||
- blob->mHasData ||
+ hasData ||
level != 0)
{
mContext->ErrorInvalidOperation("%s: With format %s, this function may only"
" be called with target=TEXTURE_2D,"
" data=null, and level=0.",
funcName, dstFormat->name);
return;
}
@@ -1283,17 +1345,17 @@ WebGLTexture::TexImage(const char* funcN
MOZ_ALWAYS_TRUE( mContext->gl->MakeCurrent() );
MOZ_ASSERT(mContext->gl->IsCurrent());
// It's tempting to do allocation first, and TexSubImage second, but this is generally
// slower.
const ImageInfo newImageInfo(dstUsage, blob->mWidth, blob->mHeight, blob->mDepth,
- blob->mHasData);
+ hasData);
const bool isSubImage = false;
const bool needsRespec = (imageInfo->mWidth != newImageInfo.mWidth ||
imageInfo->mHeight != newImageInfo.mHeight ||
imageInfo->mDepth != newImageInfo.mDepth ||
imageInfo->mFormat != newImageInfo.mFormat);
const GLint xOffset = 0;
const GLint yOffset = 0;