Bug 1313541 - Rewrite TexImageSource glue. - r=ethlin

MozReview-Commit-ID: 4zwNrobTcUf
This commit is contained in:
Jeff Gilbert (:jgilbert) 2016-10-20 18:03:40 -07:00
Родитель 4b2a875e8b
Коммит cafb4ccac4
8 изменённых файлов: 780 добавлений и 1030 удалений

Просмотреть файл

@ -131,6 +131,86 @@ FormatForPackingInfo(const PackingInfo& pi)
////////////////////
static bool
ValidateUnpackPixels(WebGLContext* webgl, const char* funcName, uint32_t fullRows,
uint32_t tailPixels, webgl::TexUnpackBlob* blob)
{
if (!blob->mWidth || !blob->mHeight || !blob->mDepth)
return true;
const auto usedPixelsPerRow = CheckedUint32(blob->mSkipPixels) + blob->mWidth;
if (!usedPixelsPerRow.isValid() || usedPixelsPerRow.value() > blob->mRowLength) {
webgl->ErrorInvalidOperation("%s: UNPACK_SKIP_PIXELS + width >"
" UNPACK_ROW_LENGTH.",
funcName);
return false;
}
if (blob->mHeight > blob->mImageHeight) {
webgl->ErrorInvalidOperation("%s: height > UNPACK_IMAGE_HEIGHT.", funcName);
return false;
}
//////
// The spec doesn't bound SKIP_ROWS + height <= IMAGE_HEIGHT, unfortunately.
auto skipFullRows = CheckedUint32(blob->mSkipImages) * blob->mImageHeight;
skipFullRows += blob->mSkipRows;
MOZ_ASSERT(blob->mDepth >= 1);
MOZ_ASSERT(blob->mHeight >= 1);
auto usedFullRows = CheckedUint32(blob->mDepth - 1) * blob->mImageHeight;
usedFullRows += blob->mHeight - 1; // Full rows in the final image, excluding the tail.
const auto fullRowsNeeded = skipFullRows + usedFullRows;
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()) {
blob->mNeedsExactUpload = true;
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,
const webgl::PackingInfo& pi, size_t availByteCount,
webgl::TexUnpackBlob* blob)
{
if (!blob->mWidth || !blob->mHeight || !blob->mDepth)
return true;
const auto bytesPerPixel = webgl::BytesPerPixel(pi);
const auto bytesPerRow = CheckedUint32(blob->mRowLength) * bytesPerPixel;
const auto rowStride = RoundUpToMultipleOf(bytesPerRow, blob->mAlignment);
const auto fullRows = availByteCount / rowStride;
if (!fullRows.isValid()) {
webgl->ErrorOutOfMemory("%s: Unacceptable upload size calculated.");
return false;
}
const auto bodyBytes = fullRows.value() * rowStride.value();
const auto tailPixels = (availByteCount - bodyBytes) / bytesPerPixel;
return ValidateUnpackPixels(webgl, funcName, fullRows.value(), tailPixels, blob);
}
////////////////////
static uint32_t
ZeroOn2D(TexImageTarget target, uint32_t val)
{
@ -331,14 +411,25 @@ DoTexOrSubImage(bool isSubImage, gl::GLContext* gl, TexImageTarget target, GLint
TexUnpackBytes::TexUnpackBytes(const WebGLContext* webgl, TexImageTarget target,
uint32_t width, uint32_t height, uint32_t depth,
bool isClientData, const uint8_t* ptr)
bool isClientData, const uint8_t* ptr, size_t availBytes)
: TexUnpackBlob(webgl, target,
FallbackOnZero(webgl->mPixelStore_UnpackRowLength, width), width,
height, depth, false)
, mIsClientData(isClientData)
, mPtr(ptr)
, mAvailBytes(availBytes)
{ }
bool
TexUnpackBytes::Validate(WebGLContext* webgl, const char* funcName,
const webgl::PackingInfo& pi)
{
if (mIsClientData && !mPtr)
return true;
return ValidateUnpackBytes(webgl, funcName, pi, mAvailBytes, this);
}
bool
TexUnpackBytes::TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
WebGLTexture* tex, TexImageTarget target, GLint level,
@ -470,6 +561,14 @@ TexUnpackImage::TexUnpackImage(const WebGLContext* webgl, TexImageTarget target,
TexUnpackImage::~TexUnpackImage()
{ }
bool
TexUnpackImage::Validate(WebGLContext* webgl, const char* funcName,
const webgl::PackingInfo& pi)
{
const auto& fullRows = mImage->GetSize().height;
return ValidateUnpackPixels(webgl, funcName, fullRows, 0, this);
}
bool
TexUnpackImage::TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
WebGLTexture* tex, TexImageTarget target, GLint level,
@ -625,6 +724,14 @@ GetFormatForSurf(gfx::SourceSurface* surf, WebGLTexelFormat* const out_texelForm
//////////
bool
TexUnpackSurface::Validate(WebGLContext* webgl, const char* funcName,
const webgl::PackingInfo& pi)
{
const auto& fullRows = mSurf->GetSize().height;
return ValidateUnpackPixels(webgl, funcName, fullRows, 0, this);
}
bool
TexUnpackSurface::TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
WebGLTexture* tex, TexImageTarget target, GLint level,

Просмотреть файл

@ -72,6 +72,8 @@ protected:
public:
virtual bool HasData() const { return true; }
virtual bool Validate(WebGLContext* webgl, const char* funcName,
const webgl::PackingInfo& pi) = 0;
virtual bool TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
WebGLTexture* tex, TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLint xOffset,
@ -84,12 +86,16 @@ class TexUnpackBytes final : public TexUnpackBlob
public:
const bool mIsClientData;
const uint8_t* const mPtr;
const size_t mAvailBytes;
TexUnpackBytes(const WebGLContext* webgl, TexImageTarget target, uint32_t width,
uint32_t height, uint32_t depth, bool isClientData, const uint8_t* ptr);
uint32_t height, uint32_t depth, bool isClientData, const uint8_t* ptr,
size_t availBytes);
virtual bool HasData() const override { return !mIsClientData || bool(mPtr); }
virtual bool Validate(WebGLContext* webgl, const char* funcName,
const webgl::PackingInfo& pi) override;
virtual bool TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
WebGLTexture* tex, TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLint xOffset,
@ -108,6 +114,8 @@ public:
~TexUnpackImage(); // Prevent needing to define layers::Image in the header.
virtual bool Validate(WebGLContext* webgl, const char* funcName,
const webgl::PackingInfo& pi) override;
virtual bool TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
WebGLTexture* tex, TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLint xOffset,
@ -124,6 +132,8 @@ public:
uint32_t height, uint32_t depth, gfx::DataSourceSurface* surf,
bool isAlphaPremult);
virtual bool Validate(WebGLContext* webgl, const char* funcName,
const webgl::PackingInfo& pi) override;
virtual bool TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
WebGLTexture* tex, TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLint xOffset,

Просмотреть файл

@ -88,84 +88,138 @@ public:
// Texture objects - WebGL2ContextTextures.cpp
void TexStorage2D(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width,
GLsizei height);
GLsizei height)
{
const char funcName[] = "TexStorage2D";
const uint8_t funcDims = 2;
const GLsizei depth = 1;
TexStorage(funcName, funcDims, target, levels, internalFormat, width, height,
depth);
}
void TexStorage3D(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width,
GLsizei height, GLsizei depth);
GLsizei height, GLsizei depth)
{
const char funcName[] = "TexStorage3D";
const uint8_t funcDims = 3;
TexStorage(funcName, funcDims, target, levels, internalFormat, width, height,
depth);
}
////
protected:
void TexStorage(const char* funcName, uint8_t funcDims, 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:
template<typename T>
void CompressedTexImage3D(GLenum target, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLsizei depth, GLint border,
const T& anySrc, GLuint viewElemOffset = 0)
{
const char funcName[] = "compressedTexImage3D";
const uint8_t funcDims = 3;
const TexImageSourceAdapter src(anySrc, viewElemOffset);
CompressedTexImage(funcName, funcDims, target, level, internalFormat, width,
height, depth, border, src);
}
template<typename T>
void CompressedTexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
GLint zOffset, GLsizei width, GLsizei height,
GLsizei depth, GLenum unpackFormat, const T& anySrc,
GLuint viewElemOffset = 0)
{
const char funcName[] = "compressedTexSubImage3D";
const uint8_t funcDims = 3;
const TexImageSourceAdapter src(anySrc, viewElemOffset);
CompressedTexSubImage(funcName, funcDims, target, level, xOffset, yOffset,
zOffset, width, height, depth, unpackFormat, src);
}
////////////////////////////////////
void CopyTexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
GLint zOffset, GLint x, GLint y, GLsizei width,
GLsizei height)
{
const char funcName[] = "copyTexSubImage3D";
const uint8_t funcDims = 3;
CopyTexSubImage(funcName, funcDims, target, level, xOffset, yOffset, zOffset,
x, y, width, height);
}
////////////////////////////////////
template<typename T>
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>& maybeSrc, ErrorResult&)
GLenum unpackType, const T& anySrc, ErrorResult& out_error)
{
const dom::ArrayBufferView* srcView = nullptr;
if (!maybeSrc.IsNull()) {
srcView = &maybeSrc.Value();
}
const TexImageSourceAdapter src(anySrc, &out_error);
TexImage3D(target, level, internalFormat, width, height, depth, border,
unpackFormat, unpackType, srcView, 0);
unpackFormat, unpackType, src);
}
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, ErrorResult&)
GLenum unpackType, const dom::ArrayBufferView& view,
GLuint viewElemOffset, ErrorResult&)
{
const TexImageSourceAdapter src(view, viewElemOffset);
TexImage3D(target, level, internalFormat, width, height, depth, border,
unpackFormat, unpackType, &srcView, srcElemOffset);
unpackFormat, unpackType, src);
}
////
protected:
void TexImage3D(GLenum target, GLint level, GLenum internalFormat, GLsizei width,
GLsizei height, GLsizei depth, GLint border, GLenum unpackFormat,
GLenum unpackType, const TexImageSource& src)
{
const char funcName[] = "texImage3D";
const uint8_t funcDims = 3;
TexImage(funcName, funcDims, target, level, internalFormat, width, height, depth,
border, unpackFormat, unpackType, src);
}
////////////////////////////////////
public:
template<typename T>
void TexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
GLint zOffset, GLsizei width, GLsizei height, GLsizei depth,
GLenum unpackFormat, GLenum unpackType, const T& anySrc,
ErrorResult& out_error)
{
const TexImageSourceAdapter src(anySrc, &out_error);
TexSubImage3D(target, level, xOffset, yOffset, zOffset, width, height, depth,
unpackFormat, unpackType, src);
}
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& 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& 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& srcView,
GLuint srcElemOffset);
////////////////
// Texture PBOs
void TexImage3D(GLenum target, GLint level, GLenum internalFormat, GLsizei width,
GLsizei height, GLsizei depth, GLint border, GLenum unpackFormat,
GLenum unpackType, WebGLsizeiptr offset, ErrorResult&);
ErrorResult&)
{
const TexImageSourceAdapter src(srcView, srcElemOffset);
TexSubImage3D(target, level, xOffset, yOffset, zOffset, width, height, depth,
unpackFormat, unpackType, src);
}
protected:
void TexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
GLint zOffset, GLsizei width, GLsizei height, GLsizei depth,
GLenum unpackFormat, GLenum unpackType, WebGLsizeiptr offset,
ErrorResult&);
GLenum unpackFormat, GLenum unpackType, const TexImageSource& src)
{
const char funcName[] = "texSubImage3D";
const uint8_t funcDims = 3;
TexSubImage(funcName, funcDims, target, level, xOffset, yOffset, zOffset, width,
height, depth, unpackFormat, unpackType, src);
}
public:
// -------------------------------------------------------------------------
// Programs and shaders - WebGL2ContextPrograms.cpp
GLint GetFragDataLocation(WebGLProgram* program, const nsAString& name);

Просмотреть файл

@ -11,308 +11,18 @@
namespace mozilla {
void
WebGL2Context::TexStorage2D(GLenum rawTexTarget, GLsizei levels, GLenum internalFormat,
GLsizei width, GLsizei height)
WebGL2Context::TexStorage(const char* funcName, uint8_t funcDims, GLenum rawTarget,
GLsizei levels, GLenum internalFormat, GLsizei width,
GLsizei height, GLsizei depth)
{
const char funcName[] = "TexStorage2D";
const uint8_t funcDims = 2;
TexTarget target;
WebGLTexture* tex;
if (!ValidateTexTarget(this, funcName, funcDims, rawTexTarget, &target, &tex))
return;
const GLsizei depth = 1;
tex->TexStorage(funcName, target, levels, internalFormat, width, height, depth);
}
void
WebGL2Context::TexStorage3D(GLenum rawTexTarget, GLsizei levels, GLenum internalFormat,
GLsizei width, GLsizei height, GLsizei depth)
{
const char funcName[] = "texStorage3D";
const uint8_t funcDims = 3;
TexTarget target;
WebGLTexture* tex;
if (!ValidateTexTarget(this, funcName, funcDims, rawTexTarget, &target, &tex))
if (!ValidateTexTarget(this, funcName, funcDims, rawTarget, &target, &tex))
return;
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::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 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, srcView, 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& 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))
{
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, &srcView, srcElemOffset);
}
void
WebGL2Context::TexSubImage3D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLint zOffset, GLenum unpackFormat,
GLenum unpackType, const dom::ImageData& imageData,
ErrorResult&)
{
const char funcName[] = "texSubImage3D";
const uint8_t funcDims = 3;
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
{
return;
}
const bool isSubImage = true;
const GLenum internalFormat = 0;
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, unpackFormat, unpackType, imageData);
}
void
WebGL2Context::TexSubImage3D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLint zOffset, GLenum unpackFormat,
GLenum unpackType, const dom::Element& elem,
ErrorResult& out_rv)
{
const char funcName[] = "texSubImage3D";
const uint8_t funcDims = 3;
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
{
return;
}
const bool isSubImage = true;
const GLenum internalFormat = 0;
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& 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, srcView, 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& 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, srcView, 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";
const uint8_t funcDims = 3;
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
{
return;
}
tex->CopyTexSubImage(funcName, target, level, xOffset, yOffset, zOffset, x, y, width,
height);
}
////////////////////
void
WebGLContext::TexImage2D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLint border,
GLenum unpackFormat, GLenum unpackType, WebGLsizeiptr offset,
ErrorResult&)
{
const char funcName[] = "texImage2D";
const uint8_t funcDims = 2;
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
{
return;
}
const bool isSubImage = false;
const GLint xOffset = 0;
const GLint yOffset = 0;
const GLint zOffset = 0;
const GLsizei depth = 1;
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, width, height, depth, border, unpackFormat,
unpackType, offset);
}
void
WebGLContext::TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLsizei width, GLsizei height,
GLenum unpackFormat, GLenum unpackType, WebGLsizeiptr offset,
ErrorResult&)
{
const char funcName[] = "texSubImage2D";
const uint8_t funcDims = 2;
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
{
return;
}
const bool isSubImage = true;
const GLenum internalFormat = 0;
const GLint zOffset = 0;
const GLsizei depth = 1;
const GLint border = 0;
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, width, height, depth, border, unpackFormat,
unpackType, offset);
}
//////////
void
WebGL2Context::TexImage3D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLsizei depth, GLint border,
GLenum unpackFormat, GLenum unpackType, WebGLsizeiptr offset,
ErrorResult&)
{
const char funcName[] = "texImage3D";
const uint8_t funcDims = 3;
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
{
return;
}
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, offset);
}
void
WebGL2Context::TexSubImage3D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLint zOffset, GLsizei width, GLsizei height,
GLsizei depth, GLenum unpackFormat, GLenum unpackType,
WebGLsizeiptr offset, ErrorResult&)
{
const char funcName[] = "texSubImage3D";
const uint8_t funcDims = 3;
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
{
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, offset);
}
////////////////////
/*virtual*/ bool

Просмотреть файл

@ -195,6 +195,62 @@ struct IndexedBufferBinding
uint64_t ByteCount() const;
};
////////////////////////////////////
struct TexImageSource
{
const dom::ArrayBufferView* mView;
GLuint mViewElemOffset;
const WebGLsizeiptr* mPboOffset;
const dom::ImageData* mImageData;
const dom::Element* mDomElem;
ErrorResult* mOut_error;
protected:
TexImageSource() {
memset(this, 0, sizeof(*this));
}
};
////
struct TexImageSourceAdapter final : public TexImageSource
{
TexImageSourceAdapter(const dom::Nullable<dom::ArrayBufferView>& maybeView,
ErrorResult*)
{
if (!maybeView.IsNull()) {
mView = &(maybeView.Value());
}
}
TexImageSourceAdapter(const dom::ArrayBufferView& view, ErrorResult*) {
mView = &view;
}
TexImageSourceAdapter(const dom::ArrayBufferView& view, GLuint viewElemOffset) {
mView = &view;
mViewElemOffset = viewElemOffset;
}
template<typename ignoredT>
TexImageSourceAdapter(WebGLsizeiptr pboOffset, ignoredT) {
mPboOffset = &pboOffset;
}
TexImageSourceAdapter(const dom::ImageData& imageData, ErrorResult*) {
mImageData = &imageData;
}
TexImageSourceAdapter(const dom::Element& domElem, ErrorResult* const out_error) {
mDomElem = &domElem;
mOut_error = out_error;
}
};
////////////////////////////////////////////////////////////////////////////////
class WebGLContext
@ -938,140 +994,185 @@ protected:
virtual bool IsTexParamValid(GLenum pname) const;
// Upload funcs
////////////////////////////////////
public:
void CompressedTexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
template<typename T>
void CompressedTexImage2D(GLenum target, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLint border,
const dom::ArrayBufferView& view, GLuint srcElemOffset = 0);
void CompressedTexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLsizei width, GLsizei height,
GLenum unpackFormat, const dom::ArrayBufferView& view,
GLuint srcElemOffset = 0);
void CopyTexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
void CopyTexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLint x, GLint y, GLsizei width,
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&)
const T& anySrc, GLuint viewElemOffset = 0)
{
const dom::ArrayBufferView* view = nullptr;
if (!maybeView.IsNull()) {
view = &(maybeView.Value());
}
TexImage2D(texImageTarget, level, internalFormat, width, height, border,
unpackFormat, unpackType, view, 0);
const char funcName[] = "compressedTexImage2D";
const uint8_t funcDims = 2;
const GLsizei depth = 1;
const TexImageSourceAdapter src(anySrc, viewElemOffset);
CompressedTexImage(funcName, funcDims, target, level, internalFormat, width,
height, depth, border, src);
}
void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLint border, GLenum unpackFormat,
GLenum unpackType, const dom::ArrayBufferView& srcView,
GLuint srcElemOffset, ErrorResult&)
template<typename T>
void CompressedTexSubImage2D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
GLsizei width, GLsizei height, GLenum unpackFormat,
const T& anySrc, GLuint viewElemOffset = 0)
{
TexImage2D(texImageTarget, level, internalFormat, width, height, border,
unpackFormat, unpackType, &srcView, srcElemOffset);
const char funcName[] = "compressedTexSubImage2D";
const uint8_t funcDims = 2;
const GLint zOffset = 0;
const GLsizei depth = 1;
const TexImageSourceAdapter src(anySrc, viewElemOffset);
CompressedTexSubImage(funcName, funcDims, target, level, xOffset, yOffset,
zOffset, width, height, depth, unpackFormat, src);
}
protected:
void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLint border, GLenum unpackFormat,
GLenum unpackType, const dom::ArrayBufferView* srcView,
GLuint srcElemOffset);
void CompressedTexImage(const char* funcName, uint8_t funcDims, GLenum target,
GLint level, GLenum internalFormat, GLsizei width,
GLsizei height, GLsizei depth, GLint border,
const TexImageSource& src);
void CompressedTexSubImage(const char* funcName, uint8_t funcDims, GLenum target,
GLint level, GLint xOffset, GLint yOffset, GLint zOffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum unpackFormat, const TexImageSource& src);
////////////////////////////////////
public:
void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
GLenum unpackFormat, GLenum unpackType,
const dom::ImageData& imageData, ErrorResult& out_error);
void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
GLenum unpackFormat, GLenum unpackType, const dom::Element& elem,
ErrorResult& out_error);
void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLint border, GLenum unpackFormat,
GLenum unpackType, WebGLsizeiptr offset, ErrorResult&);
void CopyTexImage2D(GLenum target, GLint level, GLenum internalFormat, GLint x,
GLint y, GLsizei width, GLsizei height, GLint border);
////
void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
GLenum unpackFormat, GLenum unpackType,
const dom::ImageData& imageData, ErrorResult& out_error);
void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
GLenum unpackFormat, GLenum unpackType, const dom::Element& elem,
ErrorResult& out_error);
void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
GLsizei width, GLsizei height, GLenum unpackFormat,
GLenum unpackType, WebGLsizeiptr offset, ErrorResult&);
////////////////
// dom::ImageData
void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
GLenum unpackFormat, GLenum unpackType,
const dom::ImageData* imageData, ErrorResult& out_error)
void CopyTexSubImage2D(GLenum target, GLint level, GLint xOffset,
GLint yOffset, GLint x, GLint y, GLsizei width,
GLsizei height)
{
const char funcName[] = "texImage2D";
if (IsContextLost())
return;
if (!imageData)
return ErrorInvalidValue("%s: `data` must not be null.", funcName);
TexImage2D(texImageTarget, level, internalFormat, unpackFormat, unpackType,
*imageData, out_error);
const char funcName[] = "copyTexSubImage2D";
const uint8_t funcDims = 2;
const GLint zOffset = 0;
CopyTexSubImage(funcName, funcDims, target, level, xOffset, yOffset, zOffset,
x, y, width, height);
}
void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
GLenum unpackFormat, GLenum unpackType,
const dom::ImageData* imageData, ErrorResult& out_error)
protected:
void CopyTexSubImage(const char* funcName, uint8_t funcDims, GLenum target,
GLint level, GLint xOffset, GLint yOffset, GLint zOffset,
GLint x, GLint y, GLsizei width, GLsizei height);
////////////////////////////////////
// TexImage
// Implicit width/height uploads
public:
template<typename T>
void TexImage2D(GLenum target, GLint level, GLenum internalFormat,
GLenum unpackFormat, GLenum unpackType, const T& src,
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);
GLsizei width = 0;
GLsizei height = 0;
GLint border = 0;
TexImage2D(target, level, internalFormat, width, height, border, unpackFormat,
unpackType, src, 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,
template<typename T>
void TexSubImage2D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
GLenum unpackFormat, GLenum unpackType, const T& src,
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, maybeSrc.Value(), 0, out_error);
GLsizei width = 0;
GLsizei height = 0;
TexSubImage2D(target, level, xOffset, yOffset, width, height, unpackFormat,
unpackType, src, 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&);
////
//////
template<typename T>
void TexImage2D(GLenum target, GLint level, GLenum internalFormat, GLsizei width,
GLsizei height, GLint border, GLenum unpackFormat, GLenum unpackType,
const T& anySrc, ErrorResult& out_error)
{
const TexImageSourceAdapter src(anySrc, &out_error);
TexImage2D(target, level, internalFormat, width, height, border, unpackFormat,
unpackType, src);
}
void TexImage2D(GLenum target, GLint level, GLenum internalFormat, GLsizei width,
GLsizei height, GLint border, GLenum unpackFormat, GLenum unpackType,
const dom::ArrayBufferView& view, GLuint viewElemOffset,
ErrorResult&)
{
const TexImageSourceAdapter src(view, viewElemOffset);
TexImage2D(target, level, internalFormat, width, height, border, unpackFormat,
unpackType, src);
}
protected:
void TexImage2D(GLenum target, GLint level, GLenum internalFormat, GLsizei width,
GLsizei height, GLint border, GLenum unpackFormat,
GLenum unpackType, const TexImageSource& src)
{
const char funcName[] = "texImage2D";
const uint8_t funcDims = 2;
const GLsizei depth = 1;
TexImage(funcName, funcDims, target, level, internalFormat, width, height, depth,
border, unpackFormat, unpackType, src);
}
void TexImage(const char* funcName, uint8_t funcDims, GLenum target, GLint level,
GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLenum unpackFormat, GLenum unpackType,
const TexImageSource& src);
////
public:
template<typename T>
void TexSubImage2D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
GLsizei width, GLsizei height, GLenum unpackFormat,
GLenum unpackType, const T& anySrc, ErrorResult& out_error)
{
const TexImageSourceAdapter src(anySrc, &out_error);
TexSubImage2D(target, level, xOffset, yOffset, width, height, unpackFormat,
unpackType, src);
}
void TexSubImage2D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
GLsizei width, GLsizei height, GLenum unpackFormat,
GLenum unpackType, const dom::ArrayBufferView& view,
GLuint viewElemOffset, ErrorResult&)
{
const TexImageSourceAdapter src(view, viewElemOffset);
TexSubImage2D(target, level, xOffset, yOffset, width, height, unpackFormat,
unpackType, src);
}
protected:
void TexSubImage2D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
GLsizei width, GLsizei height, GLenum unpackFormat,
GLenum unpackType, const TexImageSource& src)
{
const char funcName[] = "texSubImage2D";
const uint8_t funcDims = 2;
const GLint zOffset = 0;
const GLsizei depth = 1;
TexSubImage(funcName, funcDims, target, level, xOffset, yOffset, zOffset, width,
height, depth, unpackFormat, unpackType, src);
}
void TexSubImage(const char* funcName, uint8_t funcDims, GLenum target, GLint level,
GLint xOffset, GLint yOffset, GLint zOffset, GLsizei width,
GLsizei height, GLsizei depth, GLenum unpackFormat,
GLenum unpackType, const TexImageSource& src);
////////////////////////////////////
// WebGLTextureUpload.cpp
public:
bool ValidateUnpackPixels(const char* funcName, uint32_t fullRows,
uint32_t tailPixels, webgl::TexUnpackBlob* blob);
UniquePtr<webgl::TexUnpackBlob>
From(const char* funcName, TexImageTarget target, GLsizei rawWidth, GLsizei rawHeight,
GLsizei rawDepth, GLint border, const TexImageSource& src,
dom::Uint8ClampedArray* const scopedArr);
protected:
bool ValidateTexImageSpecification(const char* funcName, uint8_t funcDims,
@ -1088,10 +1189,19 @@ protected:
TexImageTarget* const out_target,
WebGLTexture** const out_texture,
WebGLTexture::ImageInfo** const out_imageInfo);
bool ValidateUnpackInfo(const char* funcName, bool usePBOs, GLenum format,
GLenum type, webgl::PackingInfo* const out);
UniquePtr<webgl::TexUnpackBlob>
FromDomElem(const char* funcName, TexImageTarget target, uint32_t width,
uint32_t height, uint32_t depth, const dom::Element& elem,
ErrorResult* const out_error);
UniquePtr<webgl::TexUnpackBytes>
FromCompressed(const char* funcName, TexImageTarget target, GLsizei rawWidth,
GLsizei rawHeight, GLsizei rawDepth, GLint border,
const TexImageSource& src);
// -----------------------------------------------------------------------------
// Vertices Feature (WebGLContextVertices.cpp)
GLenum mPrimRestartTypeBytes;
@ -1468,10 +1578,12 @@ protected:
return true;
}
public:
bool ValidateArrayBufferView(const char* funcName, const dom::ArrayBufferView& view,
GLuint elemOffset, GLuint elemCountOverride,
uint8_t** const out_bytes, size_t* const out_byteLen);
protected:
////
void Invalidate();

Просмотреть файл

@ -316,220 +316,44 @@ WebGLContext::TexParameter_base(GLenum rawTexTarget, GLenum pname, GLint* maybeI
tex->TexParameter(texTarget, pname, maybeIntParam, maybeFloatParam);
}
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Uploads
////////////////////
// TexImage
void
WebGLContext::TexImage2D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLint border, GLenum unpackFormat,
GLenum unpackType, const dom::ArrayBufferView* maybeView,
GLuint elemOffset)
WebGLContext::CompressedTexImage(const char* funcName, uint8_t funcDims, GLenum rawTarget,
GLint level, GLenum internalFormat, GLsizei width,
GLsizei height, GLsizei depth, GLint border,
const TexImageSource& src)
{
const char funcName[] = "texImage2D";
const uint8_t funcDims = 2;
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
{
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTarget, &target, &tex))
return;
}
const bool isSubImage = false;
const GLint xOffset = 0;
const GLint yOffset = 0;
const GLint zOffset = 0;
const GLsizei depth = 1;
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, width, height, depth, border, unpackFormat,
unpackType, maybeView, elemOffset);
}
void
WebGLContext::TexImage2D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
GLenum unpackFormat, GLenum unpackType,
const dom::ImageData& imageData, ErrorResult&)
{
const char funcName[] = "texImage2D";
const uint8_t funcDims = 2;
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
{
return;
}
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, unpackFormat, unpackType, imageData);
}
void
WebGLContext::TexImage2D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
GLenum unpackFormat, GLenum unpackType, const dom::Element& elem,
ErrorResult& out_error)
{
const char funcName[] = "texImage2D";
const uint8_t funcDims = 2;
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
{
return;
}
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, unpackFormat, unpackType, elem, &out_error);
}
////////////////////////////////////////
// TexSubImage
void
WebGLContext::TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLsizei width, GLsizei height,
GLenum unpackFormat, GLenum unpackType,
const dom::ArrayBufferView& view, GLuint elemOffset,
ErrorResult&)
{
const char funcName[] = "texSubImage2D";
const uint8_t funcDims = 2;
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
{
return;
}
const bool isSubImage = true;
const GLenum internalFormat = 0;
const GLint zOffset = 0;
const GLsizei depth = 1;
const GLint border = 0;
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, width, height, depth, border, unpackFormat,
unpackType, &view, elemOffset);
}
void
WebGLContext::TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLenum unpackFormat, GLenum unpackType,
const dom::ImageData& imageData, ErrorResult&)
{
const char funcName[] = "texSubImage2D";
const uint8_t funcDims = 2;
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
{
return;
}
const bool isSubImage = true;
const GLenum internalFormat = 0;
const GLint zOffset = 0;
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, unpackFormat, unpackType, imageData);
}
void
WebGLContext::TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLenum unpackFormat, GLenum unpackType,
const dom::Element& elem, ErrorResult& out_error)
{
const char funcName[] = "texSubImage2D";
const uint8_t funcDims = 2;
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
{
return;
}
const bool isSubImage = true;
const GLenum internalFormat = 0;
const GLint zOffset = 0;
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, unpackFormat, unpackType, elem, &out_error);
}
////////////////////////////////////////
// CompressedTex(Sub)Image
void
WebGLContext::CompressedTexImage2D(GLenum rawTexImageTarget, GLint level,
GLenum internalFormat, GLsizei width, GLsizei height,
GLint border, const dom::ArrayBufferView& srcView,
GLuint srcElemOffset)
{
const char funcName[] = "compressedTexImage2D";
const uint8_t funcDims = 2;
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
{
return;
}
const GLsizei depth = 1;
tex->CompressedTexImage(funcName, target, level, internalFormat, width, height, depth,
border, srcView, srcElemOffset);
border, src);
}
void
WebGLContext::CompressedTexSubImage2D(GLenum rawTexImageTarget, GLint level,
GLint xOffset, GLint yOffset, GLsizei width,
GLsizei height, GLenum sizedUnpackFormat,
const dom::ArrayBufferView& srcView,
GLuint srcElemOffset)
WebGLContext::CompressedTexSubImage(const char* funcName, uint8_t funcDims,
GLenum rawTarget, GLint level, GLint xOffset,
GLint yOffset, GLint zOffset, GLsizei width,
GLsizei height, GLsizei depth, GLenum unpackFormat,
const TexImageSource& src)
{
const char funcName[] = "compressedTexSubImage2D";
const uint8_t funcDims = 2;
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
{
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTarget, &target, &tex))
return;
}
const GLint zOffset = 0;
const GLsizei depth = 1;
tex->CompressedTexSubImage(funcName, target, level, xOffset, yOffset, zOffset, width,
height, depth, sizedUnpackFormat, srcView, srcElemOffset);
height, depth, unpackFormat, src);
}
////////////////////////////////////////
// CopyTex(Sub)Image
////
void
WebGLContext::CopyTexImage2D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
WebGLContext::CopyTexImage2D(GLenum rawTarget, GLint level, GLenum internalFormat,
GLint x, GLint y, GLsizei width, GLsizei height,
GLint border)
{
@ -538,35 +362,59 @@ WebGLContext::CopyTexImage2D(GLenum rawTexImageTarget, GLint level, GLenum inter
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
{
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTarget, &target, &tex))
return;
}
tex->CopyTexImage2D(target, level, internalFormat, x, y, width, height, border);
}
void
WebGLContext::CopyTexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLint x, GLint y, GLsizei width,
GLsizei height)
WebGLContext::CopyTexSubImage(const char* funcName, uint8_t funcDims, GLenum rawTarget,
GLint level, GLint xOffset, GLint yOffset, GLint zOffset,
GLint x, GLint y, GLsizei width, GLsizei height)
{
const char funcName[] = "copyTexSubImage2D";
const uint8_t funcDims = 2;
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
{
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTarget, &target, &tex))
return;
}
const GLint zOffset = 0;
tex->CopyTexSubImage(funcName, target, level, xOffset, yOffset, zOffset, x, y, width,
height);
}
////
void
WebGLContext::TexImage(const char* funcName, uint8_t funcDims, GLenum rawTarget,
GLint level, GLenum internalFormat, GLsizei width, GLsizei height,
GLsizei depth, GLint border, GLenum unpackFormat,
GLenum unpackType, const TexImageSource& src)
{
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTarget, &target, &tex))
return;
const webgl::PackingInfo pi = {unpackFormat, unpackType};
tex->TexImage(funcName, target, level, internalFormat, width, height, depth, border,
pi, src);
}
void
WebGLContext::TexSubImage(const char* funcName, uint8_t funcDims, GLenum rawTarget,
GLint level, GLint xOffset, GLint yOffset, GLint zOffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum unpackFormat, GLenum unpackType,
const TexImageSource& src)
{
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTarget, &target, &tex))
return;
const webgl::PackingInfo pi = {unpackFormat, unpackType};
tex->TexSubImage(funcName, target, level, xOffset, yOffset, zOffset, width, height,
depth, pi, src);
}
} // namespace mozilla

Просмотреть файл

@ -25,6 +25,7 @@
namespace mozilla {
class ErrorResult;
class WebGLContext;
struct TexImageSource;
namespace dom {
class Element;
@ -232,28 +233,6 @@ 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* 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,
GLint zOffset, GLenum unpackFormat, GLenum unpackType,
const dom::Element& elem, ErrorResult* const out_error);
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,
WebGLsizeiptr offset);
protected:
void TexOrSubImageBlob(bool isSubImage, const char* funcName, TexImageTarget target,
GLint level, GLenum internalFormat, GLint xOffset,
@ -277,6 +256,13 @@ protected:
public:
void TexStorage(const char* funcName, TexTarget target, GLsizei levels,
GLenum sizedFormat, GLsizei width, GLsizei height, GLsizei depth);
void TexImage(const char* funcName, TexImageTarget target, GLint level,
GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth,
GLint border, const webgl::PackingInfo& pi, const TexImageSource& src);
void TexSubImage(const char* funcName, TexImageTarget target, GLint level,
GLint xOffset, GLint yOffset, GLint zOffset, GLsizei width,
GLsizei height, GLsizei depth, const webgl::PackingInfo& pi,
const TexImageSource& src);
protected:
void TexImage(const char* funcName, TexImageTarget target, GLint level,
GLenum internalFormat, const webgl::PackingInfo& pi,
@ -287,12 +273,12 @@ protected:
public:
void CompressedTexImage(const char* funcName, TexImageTarget target, GLint level,
GLenum internalFormat, GLsizei width, GLsizei height,
GLsizei depth, GLint border,
const dom::ArrayBufferView& srcView, GLuint srcElemOffset);
GLsizei depth, GLint border, const TexImageSource& src);
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& srcView, GLuint srcElemOffset);
const TexImageSource& src);
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,

Просмотреть файл

@ -127,225 +127,85 @@ DoesJSTypeMatchUnpackType(GLenum unpackType, js::Scalar::Type jsType)
}
}
bool
WebGLContext::ValidateUnpackPixels(const char* funcName, uint32_t fullRows,
uint32_t tailPixels, webgl::TexUnpackBlob* blob)
{
auto skipPixels = CheckedUint32(blob->mSkipPixels);
skipPixels += CheckedUint32(blob->mSkipRows);
const auto usedPixelsPerRow = CheckedUint32(blob->mSkipPixels) + blob->mWidth;
if (!usedPixelsPerRow.isValid() || usedPixelsPerRow.value() > blob->mRowLength) {
ErrorInvalidOperation("%s: UNPACK_SKIP_PIXELS + height > UNPACK_ROW_LENGTH.",
funcName);
return false;
}
if (blob->mHeight > blob->mImageHeight) {
ErrorInvalidOperation("%s: height > UNPACK_IMAGE_HEIGHT.", funcName);
return false;
}
//////
// The spec doesn't bound SKIP_ROWS + height <= IMAGE_HEIGHT, unfortunately.
auto skipFullRows = CheckedUint32(blob->mSkipImages) * blob->mImageHeight;
skipFullRows += blob->mSkipRows;
MOZ_ASSERT(blob->mDepth >= 1);
MOZ_ASSERT(blob->mHeight >= 1);
auto usedFullRows = CheckedUint32(blob->mDepth - 1) * blob->mImageHeight;
usedFullRows += blob->mHeight - 1; // Full rows in the final image, excluding the tail.
const auto fullRowsNeeded = skipFullRows + usedFullRows;
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()) {
blob->mNeedsExactUpload = true;
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 bool
ValidateUnpackBytes(WebGLContext* webgl, const char* funcName, uint32_t width,
uint32_t height, uint32_t depth, const webgl::PackingInfo& pi,
size_t byteCount, webgl::TexUnpackBlob* blob)
ValidateViewType(WebGLContext* webgl, const char* funcName, GLenum unpackType,
const TexImageSource& src)
{
if (!width || !height || !depth)
if (!src.mView)
return true;
const auto& view = *(src.mView);
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.");
const auto& jsType = view.Type();
if (!DoesJSTypeMatchUnpackType(unpackType, jsType)) {
webgl->ErrorInvalidOperation("%s: ArrayBufferView type not compatible with"
" `type`.",
funcName);
return false;
}
const auto bodyBytes = fullRows.value() * rowStride.value();
const auto tailPixels = (byteCount - bodyBytes) / bytesPerPixel;
return webgl->ValidateUnpackPixels(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 (mBoundPixelUnpackBuffer &&
mBoundPixelUnpackBuffer->mNumActiveTFOs)
{
ErrorInvalidOperation("%s: Buffer is bound to an active transform feedback"
" object.",
funcName);
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;
}
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* srcView, GLuint srcElemOffset)
static bool
ValidateUnpackInfo(WebGLContext* webgl, const char* funcName,
const webgl::PackingInfo& pi)
{
uint32_t width, height, depth;
if (!ValidateExtents(mContext, funcName, rawWidth, rawHeight, rawDepth, border,
&width, &height, &depth))
{
return;
if (!webgl->mFormatUsage->AreUnpackEnumsValid(pi.format, pi.type)) {
webgl->ErrorInvalidEnum("%s: Invalid unpack format/type: 0x%04x/0x%04x", funcName,
pi.format, pi.type);
return false;
}
const bool usePBOs = false;
webgl::PackingInfo pi;
if (!mContext->ValidateUnpackInfo(funcName, usePBOs, unpackFormat, unpackType, &pi))
return;
////
const uint8_t* bytes = nullptr;
size_t byteCount = 0;
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,
const_cast<uint8_t**>(&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);
if (bytes &&
!ValidateUnpackBytes(mContext, funcName, width, height, depth, pi, byteCount,
&blob))
{
return;
}
TexOrSubImageBlob(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, pi, &blob);
return true;
}
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,
WebGLsizeiptr offset)
////////////////////////////////////////////////////////////////////////////////
static UniquePtr<webgl::TexUnpackBytes>
FromView(WebGLContext* webgl, const char* funcName, TexImageTarget target,
uint32_t width, uint32_t height, uint32_t depth,
const dom::ArrayBufferView* view, GLuint viewElemOffset)
{
uint32_t width, height, depth;
if (!ValidateExtents(mContext, funcName, rawWidth, rawHeight, rawDepth, border,
&width, &height, &depth))
{
return;
const bool isClientData = true;
const uint8_t* bytes = nullptr;
size_t availByteCount = 0;
if (view) {
if (!webgl->ValidateArrayBufferView(funcName, *view, viewElemOffset, 0,
const_cast<uint8_t**>(&bytes),
&availByteCount))
{
return nullptr;
}
}
return MakeUnique<webgl::TexUnpackBytes>(webgl, target, width, height, depth,
isClientData, bytes, availByteCount);
}
static UniquePtr<webgl::TexUnpackBytes>
FromPboOffset(WebGLContext* webgl, const char* funcName, TexImageTarget target,
uint32_t width, uint32_t height, uint32_t depth, WebGLsizeiptr pboOffset,
size_t availBufferBytes)
{
if (pboOffset < 0) {
webgl->ErrorInvalidValue("%s: offset cannot be negative.", funcName);
return nullptr;
}
const bool usePBOs = true;
webgl::PackingInfo pi;
if (!mContext->ValidateUnpackInfo(funcName, usePBOs, unpackFormat, unpackType, &pi))
return;
////
if (offset < 0) {
mContext->ErrorInvalidValue("%s: offset cannot be negative.", funcName);
return;
if (size_t(pboOffset) > availBufferBytes) {
webgl->ErrorInvalidOperation("%s: Offset is passed end of buffer.", funcName);
return nullptr;
}
availBufferBytes -= pboOffset;
const bool isClientData = false;
const auto ptr = (const uint8_t*)offset;
webgl::TexUnpackBytes blob(mContext, target, width, height, depth, isClientData, ptr);
const auto& packBuffer = mContext->mBoundPixelUnpackBuffer;
const auto bufferByteCount = packBuffer->ByteLength();
uint32_t byteCount = 0;
if (bufferByteCount >= uint64_t(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);
const auto ptr = (const uint8_t*)pboOffset;
return MakeUnique<webgl::TexUnpackBytes>(webgl, target, width, height, depth,
isClientData, ptr, availBufferBytes);
}
////////////////////////////////////////
// ImageData
static already_AddRefed<gfx::DataSourceSurface>
FromImageData(WebGLContext* webgl, const char* funcName, GLenum unpackType,
static UniquePtr<webgl::TexUnpackBlob>
FromImageData(WebGLContext* webgl, const char* funcName, TexImageTarget target,
uint32_t width, uint32_t height, uint32_t depth,
const dom::ImageData& imageData, dom::Uint8ClampedArray* scopedArr)
{
DebugOnly<bool> inited = scopedArr->Init(imageData.GetDataObject());
@ -363,83 +223,46 @@ FromImageData(WebGLContext* webgl, const char* funcName, GLenum unpackType,
uint8_t* wrappableData = (uint8_t*)data;
RefPtr<gfx::DataSourceSurface> surf =
gfx::Factory::CreateWrappingDataSourceSurface(wrappableData,
stride,
size,
const RefPtr<gfx::DataSourceSurface> surf =
gfx::Factory::CreateWrappingDataSourceSurface(wrappableData, stride, size,
surfFormat);
if (!surf) {
webgl->ErrorOutOfMemory("%s: OOM in FromImageData.", funcName);
return nullptr;
}
return surf.forget();
}
////
void
WebGLTexture::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)
{
const bool usePBOs = false;
webgl::PackingInfo pi;
if (!mContext->ValidateUnpackInfo(funcName, usePBOs, unpackFormat, unpackType, &pi))
return;
if (!width) {
width = imageData.Width();
}
// Eventually, these will be args.
const uint32_t width = imageData.Width();
const uint32_t height = imageData.Height();
const uint32_t depth = 1;
if (!height) {
height = imageData.Height();
}
dom::RootedTypedArray<dom::Uint8ClampedArray> scopedArr(dom::RootingCx());
const RefPtr<gfx::DataSourceSurface> surf = FromImageData(mContext, funcName,
unpackType, imageData,
&scopedArr);
if (!surf)
return;
////
// WhatWG "HTML Living Standard" (30 October 2015):
// "The getImageData(sx, sy, sw, sh) method [...] Pixels must be returned as
// non-premultiplied alpha values."
const bool isAlphaPremult = false;
webgl::TexUnpackSurface blob(mContext, target, width, height, depth, surf,
isAlphaPremult);
const uint32_t fullRows = imageData.Height();
const uint32_t tailPixels = 0;
if (!mContext->ValidateUnpackPixels(funcName, fullRows, tailPixels, &blob))
return;
TexOrSubImageBlob(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, pi, &blob);
return MakeUnique<webgl::TexUnpackSurface>(webgl, target, width, height, depth, surf,
isAlphaPremult);
}
////////////////////////////////////////
// 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, const dom::Element& elem,
ErrorResult* const out_error)
UniquePtr<webgl::TexUnpackBlob>
WebGLContext::FromDomElem(const char* funcName, TexImageTarget target, uint32_t width,
uint32_t height, uint32_t depth, const dom::Element& elem,
ErrorResult* const out_error)
{
const bool usePBOs = false;
webgl::PackingInfo pi;
if (!mContext->ValidateUnpackInfo(funcName, usePBOs, unpackFormat, unpackType, &pi))
return;
//////
uint32_t flags = nsLayoutUtils::SFE_WANT_IMAGE_SURFACE |
nsLayoutUtils::SFE_USE_ELEMENT_SIZE_IF_VECTOR;
if (mContext->mPixelStore_ColorspaceConversion == LOCAL_GL_NONE)
if (mPixelStore_ColorspaceConversion == LOCAL_GL_NONE)
flags |= nsLayoutUtils::SFE_NO_COLORSPACE_CONVERSION;
if (!mContext->mPixelStore_PremultiplyAlpha)
if (!mPixelStore_PremultiplyAlpha)
flags |= nsLayoutUtils::SFE_PREFER_NO_PREMULTIPLY_ALPHA;
RefPtr<gfx::DrawTarget> idealDrawTarget = nullptr; // Don't care for now.
@ -469,18 +292,20 @@ WebGLTexture::TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarge
//////
// Eventually, these will be args.
const uint32_t width = elemWidth;
const uint32_t height = elemHeight;
const uint32_t depth = 1;
if (!width) {
width = elemWidth;
}
if (!height) {
height = elemHeight;
}
////
if (!layersImage && !dataSurf) {
const bool isClientData = true;
const webgl::TexUnpackBytes blob(mContext, target, width, height, depth,
isClientData, nullptr);
TexOrSubImageBlob(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, pi, &blob);
return;
return MakeUnique<webgl::TexUnpackBytes>(this, target, width, height, depth,
isClientData, nullptr, 0);
}
//////
@ -491,13 +316,12 @@ WebGLTexture::TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarge
if (!sfer.mCORSUsed) {
auto& srcPrincipal = sfer.mPrincipal;
nsIPrincipal* dstPrincipal = mContext->GetCanvas()->NodePrincipal();
nsIPrincipal* dstPrincipal = GetCanvas()->NodePrincipal();
if (!dstPrincipal->Subsumes(srcPrincipal)) {
mContext->GenerateWarning("%s: Cross-origin elements require CORS.",
funcName);
GenerateWarning("%s: Cross-origin elements require CORS.", funcName);
out_error->Throw(NS_ERROR_DOM_SECURITY_ERR);
return;
return nullptr;
}
}
@ -505,52 +329,128 @@ WebGLTexture::TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarge
// mIsWriteOnly defaults to true, and so will be true even if SFE merely
// failed. Thus we must test mIsWriteOnly after successfully retrieving an
// Image or SourceSurface.
mContext->GenerateWarning("%s: Element is write-only, thus cannot be"
" uploaded.",
funcName);
GenerateWarning("%s: Element is write-only, thus cannot be uploaded.", funcName);
out_error->Throw(NS_ERROR_DOM_SECURITY_ERR);
return;
return nullptr;
}
//////
// Ok, we're good!
UniquePtr<webgl::TexUnpackBlob> blob;
const bool isAlphaPremult = sfer.mIsPremultiplied;
if (layersImage) {
blob.reset(new webgl::TexUnpackImage(mContext, target, width, height, depth,
layersImage, isAlphaPremult));
} else {
MOZ_ASSERT(dataSurf);
blob.reset(new webgl::TexUnpackSurface(mContext, target, width, height, depth,
dataSurf, isAlphaPremult));
return MakeUnique<webgl::TexUnpackImage>(this, target, width, height, depth,
layersImage, isAlphaPremult);
}
const uint32_t fullRows = elemHeight;
const uint32_t tailPixels = 0;
if (!mContext->ValidateUnpackPixels(funcName, fullRows, tailPixels, blob.get()))
return;
TexOrSubImageBlob(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, pi, blob.get());
MOZ_ASSERT(dataSurf);
return MakeUnique<webgl::TexUnpackSurface>(this, target, width, height, depth,
dataSurf, isAlphaPremult);
}
////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
UniquePtr<webgl::TexUnpackBlob>
WebGLContext::From(const char* funcName, TexImageTarget target, GLsizei rawWidth,
GLsizei rawHeight, GLsizei rawDepth, GLint border,
const TexImageSource& src, dom::Uint8ClampedArray* const scopedArr)
{
uint32_t width, height, depth;
if (!ValidateExtents(this, funcName, rawWidth, rawHeight, rawDepth, border, &width,
&height, &depth))
{
return nullptr;
}
if (src.mPboOffset) {
if (!mBoundPixelUnpackBuffer) {
ErrorInvalidOperation("%s: PACK_BUFFER must be non-null.", funcName);
return nullptr;
}
if (mBoundPixelUnpackBuffer->mNumActiveTFOs) {
ErrorInvalidOperation("%s: Buffer is bound to an active transform feedback"
" object.",
funcName);
return nullptr;
}
const auto& availBytes = mBoundPixelUnpackBuffer->ByteLength();
return FromPboOffset(this, funcName, target, width, height, depth,
*(src.mPboOffset), availBytes);
}
if (mBoundPixelUnpackBuffer) {
ErrorInvalidOperation("%s: PACK_BUFFER must be null.", funcName);
return nullptr;
}
if (src.mImageData) {
return FromImageData(this, funcName, target, width, height, depth,
*(src.mImageData), scopedArr);
}
if (src.mDomElem) {
return FromDomElem(funcName, target, width, height, depth, *(src.mDomElem),
src.mOut_error);
}
return FromView(this, funcName, target, width, height, depth, src.mView,
src.mViewElemOffset);
}
////////////////////////////////////////////////////////////////////////////////
static UniquePtr<webgl::TexUnpackBlob>
ValidateTexOrSubImage(WebGLContext* webgl, const char* funcName, TexImageTarget target,
GLsizei rawWidth, GLsizei rawHeight, GLsizei rawDepth,
GLint border, const webgl::PackingInfo& pi,
const TexImageSource& src, dom::Uint8ClampedArray* const scopedArr)
{
if (!ValidateUnpackInfo(webgl, funcName, pi))
return nullptr;
if (!ValidateViewType(webgl, funcName, pi.type, src))
return nullptr;
auto blob = webgl->From(funcName, target, rawWidth, rawHeight, rawDepth, border, src,
scopedArr);
if (!blob || !blob->Validate(webgl, funcName, pi))
return nullptr;
return Move(blob);
}
void
WebGLTexture::TexOrSubImageBlob(bool isSubImage, const char* funcName,
TexImageTarget target, GLint level, GLenum internalFormat,
GLint xOffset, GLint yOffset, GLint zOffset,
const webgl::PackingInfo& pi,
const webgl::TexUnpackBlob* blob)
WebGLTexture::TexImage(const char* funcName, TexImageTarget target, GLint level,
GLenum internalFormat, GLsizei width, GLsizei height,
GLsizei depth, GLint border, const webgl::PackingInfo& pi,
const TexImageSource& src)
{
if (isSubImage) {
TexSubImage(funcName, target, level, xOffset, yOffset, zOffset, pi, blob);
} else {
TexImage(funcName, target, level, internalFormat, pi, blob);
}
dom::RootedTypedArray<dom::Uint8ClampedArray> scopedArr(dom::RootingCx());
const auto blob = ValidateTexOrSubImage(mContext, funcName, target, width, height,
depth, border, pi, src, &scopedArr);
if (!blob)
return;
TexImage(funcName, target, level, internalFormat, pi, blob.get());
}
void
WebGLTexture::TexSubImage(const char* funcName, TexImageTarget target, GLint level,
GLint xOffset, GLint yOffset, GLint zOffset, GLsizei width,
GLsizei height, GLsizei depth,
const webgl::PackingInfo& pi, const TexImageSource& src)
{
const GLint border = 0;
dom::RootedTypedArray<dom::Uint8ClampedArray> scopedArr(dom::RootingCx());
const auto blob = ValidateTexOrSubImage(mContext, funcName, target, width, height,
depth, border, pi, src, &scopedArr);
if (!blob)
return;
TexSubImage(funcName, target, level, xOffset, yOffset, zOffset, pi, blob.get());
}
//////////////////////////////////////////////////////////////////////////////////////////
@ -1449,26 +1349,62 @@ WebGLTexture::TexSubImage(const char* funcName, TexImageTarget target, GLint lev
////////////////////////////////////////
// CompressedTex(Sub)Image
UniquePtr<webgl::TexUnpackBytes>
WebGLContext::FromCompressed(const char* funcName, TexImageTarget target,
GLsizei rawWidth, GLsizei rawHeight, GLsizei rawDepth,
GLint border, const TexImageSource& src)
{
uint32_t width, height, depth;
if (!ValidateExtents(this, funcName, rawWidth, rawHeight, rawDepth, border, &width,
&height, &depth))
{
return nullptr;
}
if (src.mPboOffset) {
if (!mBoundPixelUnpackBuffer) {
ErrorInvalidOperation("%s: PACK_BUFFER must be non-null.", funcName);
return nullptr;
}
if (mBoundPixelUnpackBuffer->mNumActiveTFOs) {
ErrorInvalidOperation("%s: Buffer is bound to an active transform feedback"
" object.",
funcName);
return nullptr;
}
const auto& availBytes = mBoundPixelUnpackBuffer->ByteLength();
return FromPboOffset(this, funcName, target, width, height, depth,
*(src.mPboOffset), availBytes);
}
if (mBoundPixelUnpackBuffer) {
ErrorInvalidOperation("%s: PACK_BUFFER must be null.", funcName);
return nullptr;
}
return FromView(this, funcName, target, width, height, depth, src.mView,
src.mViewElemOffset);
}
void
WebGLTexture::CompressedTexImage(const char* funcName, TexImageTarget target, GLint level,
GLenum internalFormat, GLsizei rawWidth,
GLsizei rawHeight, GLsizei rawDepth, GLint border,
const dom::ArrayBufferView& srcView,
GLuint srcElemOffset)
const TexImageSource& src)
{
uint32_t width, height, depth;
if (!ValidateExtents(mContext, funcName, rawWidth, rawHeight, rawDepth, border,
&width, &height, &depth))
{
const auto blob = mContext->FromCompressed(funcName, target, rawWidth, rawHeight,
rawDepth, border, src);
if (!blob)
return;
}
////////////////////////////////////
// Get dest info
WebGLTexture::ImageInfo* imageInfo;
if (!ValidateTexImageSpecification(funcName, target, level, width, height, depth,
&imageInfo))
if (!ValidateTexImageSpecification(funcName, target, level, blob->mWidth,
blob->mHeight, blob->mDepth, &imageInfo))
{
return;
}
@ -1494,16 +1430,8 @@ WebGLTexture::CompressedTexImage(const char* funcName, TexImageTarget target, GL
////////////////////////////////////
// Get source info
const uint8_t* bytes;
size_t byteLen;
if (!mContext->ValidateArrayBufferView(funcName, srcView, srcElemOffset, 0,
const_cast<uint8_t**>(&bytes), &byteLen))
{
return;
}
if (!ValidateCompressedTexUnpack(mContext, funcName, width, height, depth, format,
byteLen))
if (!ValidateCompressedTexUnpack(mContext, funcName, blob->mWidth, blob->mHeight,
blob->mDepth, format, blob->mAvailBytes))
{
return;
}
@ -1512,7 +1440,8 @@ WebGLTexture::CompressedTexImage(const char* funcName, TexImageTarget target, GL
// Check that source is compatible with dest
if (!ValidateCompressedTexImageRestrictions(funcName, mContext, target, level, format,
width, height, depth))
blob->mWidth, blob->mHeight,
blob->mDepth))
{
return;
}
@ -1524,7 +1453,8 @@ WebGLTexture::CompressedTexImage(const char* funcName, TexImageTarget target, GL
// Warning: Possibly shared memory. See bug 1225033.
GLenum error = DoCompressedTexImage(mContext->gl, target, level, internalFormat,
width, height, depth, byteLen, bytes);
blob->mWidth, blob->mHeight, blob->mDepth,
blob->mAvailBytes, blob->mPtr);
if (error == LOCAL_GL_OUT_OF_MEMORY) {
mContext->ErrorOutOfMemory("%s: Ran out of memory during upload.", funcName);
return;
@ -1542,7 +1472,8 @@ WebGLTexture::CompressedTexImage(const char* funcName, TexImageTarget target, GL
// Update our specification data.
const bool isDataInitialized = true;
const ImageInfo newImageInfo(usage, width, height, depth, isDataInitialized);
const ImageInfo newImageInfo(usage, blob->mWidth, blob->mHeight, blob->mDepth,
isDataInitialized);
SetImageInfo(imageInfo, newImageInfo);
}
@ -1571,22 +1502,20 @@ 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& srcView,
GLuint srcElemOffset)
const TexImageSource& src)
{
uint32_t width, height, depth;
if (!ValidateExtents(mContext, funcName, rawWidth, rawHeight, rawDepth, 0, &width,
&height, &depth))
{
const GLint border = 0;
const auto blob = mContext->FromCompressed(funcName, target, rawWidth, rawHeight,
rawDepth, border, src);
if (!blob)
return;
}
////////////////////////////////////
// Get dest info
WebGLTexture::ImageInfo* imageInfo;
if (!ValidateTexImageSelection(funcName, target, level, xOffset, yOffset, zOffset,
width, height, depth, &imageInfo))
blob->mWidth, blob->mHeight, blob->mDepth, &imageInfo))
{
return;
}
@ -1598,14 +1527,6 @@ WebGLTexture::CompressedTexSubImage(const char* funcName, TexImageTarget target,
////////////////////////////////////
// Get source info
const uint8_t* bytes;
size_t byteLen;
if (!mContext->ValidateArrayBufferView(funcName, srcView, srcElemOffset, 0,
const_cast<uint8_t**>(&bytes), &byteLen))
{
return;
}
auto srcUsage = mContext->mFormatUsage->GetSizedTexUsage(sizedUnpackFormat);
if (!srcUsage->format->compression) {
mContext->ErrorInvalidEnum("%s: Specified format must be compressed.", funcName);
@ -1621,8 +1542,8 @@ WebGLTexture::CompressedTexSubImage(const char* funcName, TexImageTarget target,
auto format = srcUsage->format;
MOZ_ASSERT(format == dstFormat);
if (!ValidateCompressedTexUnpack(mContext, funcName, width, height, depth, format,
byteLen))
if (!ValidateCompressedTexUnpack(mContext, funcName, blob->mWidth, blob->mHeight,
blob->mDepth, format, blob->mAvailBytes))
{
return;
}
@ -1642,7 +1563,7 @@ WebGLTexture::CompressedTexSubImage(const char* funcName, TexImageTarget target,
case webgl::CompressionFamily::ES3: // Yes, the ES3 formats don't match the ES3
case webgl::CompressionFamily::S3TC: // default behavior.
if (!IsSubImageBlockAligned(dstFormat->compression, imageInfo, xOffset, yOffset,
width, height))
blob->mWidth, blob->mHeight))
{
mContext->ErrorInvalidOperation("%s: Format requires block-aligned sub-image"
" updates.",
@ -1654,8 +1575,8 @@ WebGLTexture::CompressedTexSubImage(const char* funcName, TexImageTarget target,
// Full-only: (The ES3 default)
default: // PVRTC
if (xOffset || yOffset ||
uint32_t(width) != imageInfo->mWidth ||
uint32_t(height) != imageInfo->mHeight)
blob->mWidth != imageInfo->mWidth ||
blob->mHeight != imageInfo->mHeight)
{
mContext->ErrorInvalidOperation("%s: Format does not allow partial sub-image"
" updates.",
@ -1672,16 +1593,18 @@ WebGLTexture::CompressedTexSubImage(const char* funcName, TexImageTarget target,
bool uploadWillInitialize;
if (!EnsureImageDataInitializedForUpload(this, funcName, target, level, xOffset,
yOffset, zOffset, width, height, depth,
imageInfo, &uploadWillInitialize))
yOffset, zOffset, blob->mWidth,
blob->mHeight, blob->mDepth, imageInfo,
&uploadWillInitialize))
{
return;
}
// Warning: Possibly shared memory. See bug 1225033.
GLenum error = DoCompressedTexSubImage(mContext->gl, target, level, xOffset, yOffset,
zOffset, width, height, depth,
sizedUnpackFormat, byteLen, bytes);
zOffset, blob->mWidth, blob->mHeight,
blob->mDepth, sizedUnpackFormat,
blob->mAvailBytes, blob->mPtr);
if (error == LOCAL_GL_OUT_OF_MEMORY) {
mContext->ErrorOutOfMemory("%s: Ran out of memory during upload.", funcName);
return;