--- a/dom/canvas/TexUnpackBlob.cpp
+++ b/dom/canvas/TexUnpackBlob.cpp
@@ -14,284 +14,326 @@
#include "nsLayoutUtils.h"
#include "WebGLContext.h"
#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)
- : 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) {
- return DoTexSubImage(gl, target, level, xOffset, yOffset, zOffset, width, height,
- depth, dui->ToPacking(), data);
- } else {
- return DoTexImage(gl, target, level, dui, width, height, depth, data);
- }
-}
-
-/*static*/ void
-TexUnpackBlob::OriginsForDOM(WebGLContext* webgl, gl::OriginPos* const out_src,
- gl::OriginPos* const out_dst)
-{
- // Our surfaces are TopLeft.
- *out_src = gl::OriginPos::TopLeft;
-
- // WebGL specs the default as passing DOM elements top-left first.
- // Thus y-flip would give us bottom-left.
- *out_dst = webgl->mPixelStore_FlipY ? gl::OriginPos::BottomLeft
- : gl::OriginPos::TopLeft;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// TexUnpackBytes
-
-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)
- : TexUnpackBlob(webgl, webgl->mPixelStore_UnpackAlignment,
- FallbackOnZero(webgl->mPixelStore_UnpackRowLength, width),
- FallbackOnZero(webgl->mPixelStore_UnpackImageHeight, height),
- width, height, depth, bool(bytes))
- , mBytes(bytes)
-{ }
-
static bool
UnpackFormatHasAlpha(GLenum unpackFormat)
{
switch (unpackFormat) {
case LOCAL_GL_ALPHA:
case LOCAL_GL_LUMINANCE_ALPHA:
case LOCAL_GL_RGBA:
return true;
default:
return false;
}
}
static WebGLTexelFormat
-FormatFromPacking(const webgl::PackingInfo& pi)
+FormatForPackingInfo(const PackingInfo& pi)
{
switch (pi.type) {
+ case LOCAL_GL_UNSIGNED_BYTE:
+ switch (pi.format) {
+ case LOCAL_GL_RED:
+ case LOCAL_GL_LUMINANCE:
+ case LOCAL_GL_RED_INTEGER:
+ return WebGLTexelFormat::R8;
+
+ case LOCAL_GL_ALPHA:
+ return WebGLTexelFormat::A8;
+
+ case LOCAL_GL_LUMINANCE_ALPHA:
+ return WebGLTexelFormat::RA8;
+
+ case LOCAL_GL_RGB:
+ case LOCAL_GL_RGB_INTEGER:
+ return WebGLTexelFormat::RGB8;
+
+ case LOCAL_GL_RGBA:
+ case LOCAL_GL_RGBA_INTEGER:
+ return WebGLTexelFormat::RGBA8;
+
+ case LOCAL_GL_RG:
+ case LOCAL_GL_RG_INTEGER:
+ return WebGLTexelFormat::RG8;
+
+ default:
+ break;
+ }
+ break;
+
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
- return WebGLTexelFormat::RGB565;
+ if (pi.format == LOCAL_GL_RGB)
+ return WebGLTexelFormat::RGB565;
+ break;
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
- return WebGLTexelFormat::RGBA5551;
+ if (pi.format == LOCAL_GL_RGBA)
+ return WebGLTexelFormat::RGBA5551;
+ break;
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
- return WebGLTexelFormat::RGBA4444;
-
- case LOCAL_GL_UNSIGNED_BYTE:
- switch (pi.format) {
- case LOCAL_GL_LUMINANCE: return WebGLTexelFormat::R8;
- case LOCAL_GL_ALPHA: return WebGLTexelFormat::A8;
- case LOCAL_GL_LUMINANCE_ALPHA: return WebGLTexelFormat::RA8;
- case LOCAL_GL_RGB: return WebGLTexelFormat::RGB8;
- case LOCAL_GL_SRGB: return WebGLTexelFormat::RGB8;
- case LOCAL_GL_RGBA: return WebGLTexelFormat::RGBA8;
- case LOCAL_GL_SRGB_ALPHA: return WebGLTexelFormat::RGBA8;
- }
+ if (pi.format == LOCAL_GL_RGBA)
+ return WebGLTexelFormat::RGBA4444;
+ break;
case LOCAL_GL_HALF_FLOAT:
case LOCAL_GL_HALF_FLOAT_OES:
switch (pi.format) {
- case LOCAL_GL_LUMINANCE: return WebGLTexelFormat::R16F;
- case LOCAL_GL_ALPHA: return WebGLTexelFormat::A16F;
- case LOCAL_GL_LUMINANCE_ALPHA: return WebGLTexelFormat::RA16F;
- case LOCAL_GL_RGB: return WebGLTexelFormat::RGB16F;
- case LOCAL_GL_RGBA: return WebGLTexelFormat::RGBA16F;
+ case LOCAL_GL_RED:
+ case LOCAL_GL_LUMINANCE:
+ return WebGLTexelFormat::R16F;
+
+ case LOCAL_GL_ALPHA: return WebGLTexelFormat::A16F;
+ case LOCAL_GL_LUMINANCE_ALPHA: return WebGLTexelFormat::RA16F;
+ case LOCAL_GL_RG: return WebGLTexelFormat::RG16F;
+ case LOCAL_GL_RGB: return WebGLTexelFormat::RGB16F;
+ case LOCAL_GL_RGBA: return WebGLTexelFormat::RGBA16F;
+
+ default:
+ break;
}
+ break;
case LOCAL_GL_FLOAT:
switch (pi.format) {
- case LOCAL_GL_LUMINANCE: return WebGLTexelFormat::R32F;
- case LOCAL_GL_ALPHA: return WebGLTexelFormat::A32F;
- case LOCAL_GL_LUMINANCE_ALPHA: return WebGLTexelFormat::RA32F;
- case LOCAL_GL_RGB: return WebGLTexelFormat::RGB32F;
- case LOCAL_GL_RGBA: return WebGLTexelFormat::RGBA32F;
+ case LOCAL_GL_RED:
+ case LOCAL_GL_LUMINANCE:
+ return WebGLTexelFormat::R32F;
+
+ case LOCAL_GL_ALPHA: return WebGLTexelFormat::A32F;
+ case LOCAL_GL_LUMINANCE_ALPHA: return WebGLTexelFormat::RA32F;
+ case LOCAL_GL_RG: return WebGLTexelFormat::RG32F;
+ case LOCAL_GL_RGB: return WebGLTexelFormat::RGB32F;
+ case LOCAL_GL_RGBA: return WebGLTexelFormat::RGBA32F;
+
+ default:
+ break;
}
+ break;
+
+ case LOCAL_GL_UNSIGNED_INT_10F_11F_11F_REV:
+ if (pi.format == LOCAL_GL_RGB)
+ return WebGLTexelFormat::RGB11F11F10F;
+ break;
+
+ default:
+ break;
}
return WebGLTexelFormat::FormatNotSupportingAnyConversion;
}
+////////////////////
+
+static uint32_t
+FallbackOnZero(uint32_t val, uint32_t fallback)
+{
+ return (val ? val : fallback);
+}
+
+TexUnpackBlob::TexUnpackBlob(const WebGLContext* webgl, TexImageTarget target,
+ uint32_t rowLength, uint32_t width, uint32_t height,
+ uint32_t depth, bool isSrcPremult)
+ : mAlignment(webgl->mPixelStore_UnpackAlignment)
+ , mRowLength(rowLength)
+ , mImageHeight(FallbackOnZero(webgl->mPixelStore_UnpackImageHeight, height))
+
+ , mSkipPixels(webgl->mPixelStore_UnpackSkipPixels)
+ , mSkipRows(webgl->mPixelStore_UnpackSkipRows)
+ , mSkipImages(IsTarget3D(target) ? webgl->mPixelStore_UnpackSkipImages : 0)
+
+ , mWidth(width)
+ , mHeight(height)
+ , mDepth(depth)
+
+ , mIsSrcPremult(isSrcPremult)
+{
+ MOZ_ASSERT_IF(!IsTarget3D(target), mDepth == 1);
+}
+
+bool
+TexUnpackBlob::ConvertIfNeeded(WebGLContext* webgl, const char* funcName,
+ const void* srcBytes, uint32_t srcStride, uint8_t srcBPP,
+ WebGLTexelFormat srcFormat,
+ const webgl::DriverUnpackInfo* dstDUI,
+ const void** const out_bytes,
+ UniqueBuffer* const out_anchoredBuffer) const
+{
+ *out_bytes = srcBytes;
+
+ if (!HasData() || !mWidth || !mHeight || !mDepth)
+ return true;
+
+ //////
+
+ const auto totalSkipRows = mSkipRows + CheckedUint32(mSkipImages) * mImageHeight;
+ const auto offset = mSkipPixels * CheckedUint32(srcBPP) + totalSkipRows * srcStride;
+ if (!offset.isValid()) {
+ webgl->ErrorOutOfMemory("%s: Invalid offset calculation during conversion.",
+ funcName);
+ return false;
+ }
+ const uint32_t skipBytes = offset.value();
+
+ auto const srcBegin = (const uint8_t*)srcBytes + skipBytes;
+
+ //////
+
+ const auto srcOrigin = (webgl->mPixelStore_FlipY ? gl::OriginPos::TopLeft
+ : gl::OriginPos::BottomLeft);
+ const auto dstOrigin = gl::OriginPos::BottomLeft;
+ const bool isDstPremult = webgl->mPixelStore_PremultiplyAlpha;
+
+ const auto pi = dstDUI->ToPacking();
+ const auto dstFormat = FormatForPackingInfo(pi);
+
+ const auto dstBPP = webgl::BytesPerPixel(pi);
+ const auto dstWidthBytes = CheckedUint32(dstBPP) * mWidth;
+ const auto dstRowLengthBytes = CheckedUint32(dstBPP) * mRowLength;
+
+ const auto dstAlignment = mAlignment;
+ const auto dstStride = RoundUpToMultipleOf(dstRowLengthBytes, dstAlignment);
+
+ //////
+
+ const auto dstTotalRows = CheckedUint32(mDepth - 1) * mImageHeight + mHeight;
+
+ const auto dstSize = skipBytes + (dstTotalRows - 1) * dstStride + dstWidthBytes;
+ if (!dstSize.isValid()) {
+ webgl->ErrorOutOfMemory("%s: Invalid dstSize calculation during conversion.",
+ funcName);
+ return false;
+ }
+
+ //////
+
+ bool needsConvert = (srcOrigin != dstOrigin ||
+ srcFormat != dstFormat ||
+ srcStride != dstStride.value());
+
+ if (UnpackFormatHasAlpha(dstDUI->unpackFormat)) {
+ needsConvert |= (mIsSrcPremult != isDstPremult);
+ }
+
+ if (!needsConvert)
+ return true;
+
+ ////////////
+ // Ugh, ok, fine!
+
+ webgl->GenerateWarning("%s: Incurred CPU data conversion, which is slow.",
+ funcName);
+
+ //////
+
+ *out_anchoredBuffer = calloc(1, dstSize.value());
+ if (!out_anchoredBuffer->get()) {
+ webgl->ErrorOutOfMemory("%s: Unable to allocate buffer during conversion.",
+ funcName);
+ return false;
+ }
+ const auto dstBegin = (uint8_t*)out_anchoredBuffer->get() + skipBytes;
+
+ //////
+
+ // And go!:
+ bool wasTrivial;
+ if (!ConvertImage(mWidth, dstTotalRows.value(),
+ srcBegin, srcStride, srcOrigin, srcFormat, mIsSrcPremult,
+ dstBegin, dstStride.value(), dstOrigin, dstFormat, isDstPremult,
+ &wasTrivial))
+ {
+ webgl->ErrorImplementationBug("%s: ConvertImage failed.", funcName);
+ return false;
+ }
+
+ if (!wasTrivial) {
+ webgl->GenerateWarning("%s: Chosen format/type incurred an expensive reformat:"
+ " 0x%04x/0x%04x",
+ funcName, dstDUI->unpackFormat, dstDUI->unpackType);
+ }
+
+ *out_bytes = out_anchoredBuffer->get();
+ return true;
+}
+
+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) {
+ return DoTexSubImage(gl, target, level, xOffset, yOffset, zOffset, width, height,
+ depth, dui->ToPacking(), data);
+ } else {
+ return DoTexImage(gl, target, level, dui, width, height, depth, data);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// TexUnpackBytes
+
+TexUnpackBytes::TexUnpackBytes(const WebGLContext* webgl, TexImageTarget target,
+ uint32_t width, uint32_t height, uint32_t depth,
+ const void* bytes)
+ : TexUnpackBlob(webgl, target,
+ FallbackOnZero(webgl->mPixelStore_UnpackRowLength, width), width,
+ height, depth, false)
+ , mBytes(bytes)
+{ }
+
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;
- UniqueBuffer tempBuffer;
-
- do {
- if (!mBytes || !mWidth || !mHeight || !mDepth)
- break;
-
- if (webgl->IsWebGL2())
- break;
- MOZ_ASSERT(mDepth == 1);
-
- 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;
-
- if (!needsYFlip && !needsAlphaPremult)
- break;
-
- ////////////
- // This is literally the worst.
+ const auto pi = dui->ToPacking();
+ const auto format = FormatForPackingInfo(pi);
- if (mSkipPixels || mSkipRows || mSkipImages ||
- mRowLength != mWidth ||
- mImageHeight != mHeight)
- {
- webgl->ErrorInvalidOperation("%s: FLIP_Y and PREMULTIPLY_ALPHA are"
- " incompatible with WebGL 2's new UNPACK_*"
- " settings.",
- funcName);
- return false;
- }
-
- if (mDepth != 1) {
- webgl->ErrorInvalidOperation("%s: FLIP_Y and PREMULTIPLY_ALPHA are"
- " incompatible with 3D textures.",
- funcName);
- return false;
- }
-
- webgl->GenerateWarning("%s: Uploading ArrayBuffers with FLIP_Y or"
- " PREMULTIPLY_ALPHA is slow.",
- funcName);
-
- const auto bytesPerPixel = webgl::BytesPerPixel(pi);
-
- const auto bytesPerRow = CheckedUint32(mRowLength) * bytesPerPixel;
- const auto rowStride = RoundUpToMultipleOf(bytesPerRow, mAlignment);
- const auto imageStride = rowStride * mImageHeight;
-
- if (!imageStride.isValid()) {
- webgl->ErrorOutOfMemory("%s: Invalid calculation during"
- " FLIP_Y/PREMULTIPLY_ALPHA handling.",
- funcName);
- return false;
- }
+ const auto bytesPerPixel = webgl::BytesPerPixel(pi);
+ const auto bytesPerRow = CheckedUint32(mRowLength) * bytesPerPixel;
+ const auto rowStride = RoundUpToMultipleOf(bytesPerRow, mAlignment);
+ if (!rowStride.isValid()) {
+ MOZ_CRASH("Should be checked earlier.");
+ }
- tempBuffer = malloc(imageStride.value());
- if (!tempBuffer) {
- 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* 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();
- break;
- }
+ const void* uploadBytes;
+ UniqueBuffer tempBuffer;
+ if (!ConvertIfNeeded(webgl, funcName, mBytes, rowStride.value(), bytesPerPixel,
+ format, dui, &uploadBytes, &tempBuffer))
+ {
+ return false;
+ }
- 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.",
- funcName);
- return false;
- }
-
- const auto srcOrigin = gl::OriginPos::BottomLeft;
- const auto dstOrigin = (needsYFlip ? gl::OriginPos::TopLeft
- : gl::OriginPos::BottomLeft);
-
- 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,
- 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();
- } while (false);
-
- *out_error = DoTexOrSubImage(isSubImage, gl, target, level, dui, xOffset, yOffset,
- zOffset, mWidth, mHeight, mDepth, uploadBytes);
+ *out_error = DoTexOrSubImage(isSubImage, webgl->gl, target, level, dui, xOffset,
+ yOffset, zOffset, mWidth, mHeight, mDepth, uploadBytes);
return true;
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// TexUnpackImage
-TexUnpackImage::TexUnpackImage(const WebGLContext* webgl, uint32_t imageHeight,
+TexUnpackImage::TexUnpackImage(const WebGLContext* webgl, TexImageTarget target,
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)
+ layers::Image* image, bool isAlphaPremult)
+ : TexUnpackBlob(webgl, target, image->GetSize().width, width, height, depth,
+ isAlphaPremult)
, 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,
GLint yOffset, GLint zOffset, GLenum* const out_error) const
{
@@ -306,16 +348,23 @@ TexUnpackImage::TexOrSubImage(bool isSub
*out_error = DoTexOrSubImage(isSubImage, gl, target.get(), level, dui, xOffset,
yOffset, zOffset, mWidth, mHeight, mDepth,
nullptr);
if (*out_error)
return false;
}
do {
+ if (mDepth != 1)
+ break;
+
+ const bool isDstPremult = webgl->mPixelStore_PremultiplyAlpha;
+ if (mIsSrcPremult != isDstPremult)
+ break;
+
if (dui->unpackFormat != LOCAL_GL_RGB && dui->unpackFormat != LOCAL_GL_RGBA)
break;
if (dui->unpackType != LOCAL_GL_UNSIGNED_BYTE)
break;
gl::ScopedFramebuffer scopedFB(gl);
gl::ScopedBindFramebuffer bindFB(gl, scopedFB.FB());
@@ -329,530 +378,166 @@ TexUnpackImage::TexOrSubImage(bool isSub
if (errorScope.GetError())
break;
}
const GLenum status = gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE)
break;
- gl::OriginPos srcOrigin, dstOrigin;
- OriginsForDOM(webgl, &srcOrigin, &dstOrigin);
-
const gfx::IntSize destSize(mWidth, mHeight);
+ const auto dstOrigin = (webgl->mPixelStore_FlipY ? gl::OriginPos::TopLeft
+ : gl::OriginPos::BottomLeft);
if (!gl->BlitHelper()->BlitImageToFramebuffer(mImage, destSize, scopedFB.FB(),
dstOrigin))
{
break;
}
// Blitting was successful, so we're done!
*out_error = 0;
return true;
} while (false);
webgl->GenerateWarning("%s: Failed to hit GPU-copy fast-path. Falling back to CPU"
" upload.",
funcName);
- RefPtr<SourceSurface> surface = mImage->GetAsSourceSurface();
- if (!surface) {
- webgl->ErrorOutOfMemory("%s: GetAsSourceSurface failed after blit failed for"
- " TexUnpackImage.",
+ const RefPtr<SourceSurface> surf = mImage->GetAsSourceSurface();
+
+ RefPtr<DataSourceSurface> dataSurf;
+ if (surf) {
+ // WARNING: OSX can lose our MakeCurrent here.
+ dataSurf = surf->GetDataSurface();
+ }
+ if (!dataSurf) {
+ webgl->ErrorOutOfMemory("%s: GetAsSourceSurface or GetDataSurface failed after"
+ " blit failed for TexUnpackImage.",
funcName);
return false;
}
- TexUnpackSurface surfBlob(webgl, mImageHeight, mWidth, mHeight, mDepth, surface,
- mIsAlphaPremult);
+ const TexUnpackSurface surfBlob(webgl, target, mWidth, mHeight, mDepth, dataSurf,
+ mIsSrcPremult);
return surfBlob.TexOrSubImage(isSubImage, needsRespec, funcName, tex, target, level,
dui, xOffset, yOffset, zOffset, out_error);
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// TexUnpackSurface
-TexUnpackSurface::TexUnpackSurface(const WebGLContext* webgl, uint32_t imageHeight,
+TexUnpackSurface::TexUnpackSurface(const WebGLContext* webgl, TexImageTarget target,
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)
+ gfx::DataSourceSurface* surf, bool isAlphaPremult)
+ : TexUnpackBlob(webgl, target, surf->GetSize().width, width, height, depth,
+ isAlphaPremult)
, mSurf(surf)
- , mIsAlphaPremult(isAlphaPremult)
{ }
//////////
static bool
-GuessAlignment(const void* data, size_t bytesPerRow, size_t stride, size_t maxAlignment,
- size_t* const out_alignment)
-{
- size_t alignmentGuess = maxAlignment;
- while (alignmentGuess) {
- size_t guessStride = RoundUpToMultipleOf(bytesPerRow, alignmentGuess);
- if (guessStride == stride &&
- uintptr_t(data) % alignmentGuess == 0)
- {
- *out_alignment = alignmentGuess;
- return true;
- }
- alignmentGuess /= 2;
- }
- return false;
-}
-
-static bool
-SupportsBGRA(gl::GLContext* gl)
-{
- if (gl->IsANGLE())
- return true;
-
- return false;
-}
-
-/*static*/ bool
-TexUnpackSurface::UploadDataSurface(bool isSubImage, WebGLContext* webgl,
- TexImageTarget target, GLint level,
- const webgl::DriverUnpackInfo* dui, GLint xOffset,
- GLint yOffset, GLint zOffset, GLsizei width,
- GLsizei height, gfx::DataSourceSurface* surf,
- bool isSurfAlphaPremult, GLenum* const out_glError)
+GetFormatForSurf(gfx::SourceSurface* surf, WebGLTexelFormat* const out_texelFormat,
+ uint8_t* const out_bpp)
{
- gl::GLContext* gl = webgl->GL();
- MOZ_ASSERT(gl->IsCurrent());
- *out_glError = 0;
-
- if (isSurfAlphaPremult != webgl->mPixelStore_PremultiplyAlpha)
- return false;
-
- gl::OriginPos srcOrigin, dstOrigin;
- OriginsForDOM(webgl, &srcOrigin, &dstOrigin);
- if (srcOrigin != dstOrigin)
- return false;
-
- // This differs from the raw-data upload in that we choose how we do the unpack.
- // (alignment, etc.)
-
- // Uploading RGBX as RGBA and blitting to RGB is faster than repacking RGBX into
- // RGB on the CPU. However, this is optimization is out-of-scope for now.
-
- static const webgl::DriverUnpackInfo kInfoBGRA = {
- LOCAL_GL_BGRA,
- LOCAL_GL_BGRA,
- LOCAL_GL_UNSIGNED_BYTE,
- };
-
- const webgl::DriverUnpackInfo* chosenDUI = nullptr;
-
- switch (surf->GetFormat()) {
- case gfx::SurfaceFormat::B8G8R8A8:
- if (SupportsBGRA(gl) &&
- dui->internalFormat == LOCAL_GL_RGBA &&
- dui->unpackFormat == LOCAL_GL_RGBA &&
- dui->unpackType == LOCAL_GL_UNSIGNED_BYTE)
- {
- chosenDUI = &kInfoBGRA;
- }
- break;
-
- case gfx::SurfaceFormat::R8G8B8A8:
- if (dui->unpackFormat == LOCAL_GL_RGBA &&
- dui->unpackType == LOCAL_GL_UNSIGNED_BYTE)
- {
- chosenDUI = dui;
- }
- break;
-
- case gfx::SurfaceFormat::R5G6B5_UINT16:
- if (dui->unpackFormat == LOCAL_GL_RGB &&
- dui->unpackType == LOCAL_GL_UNSIGNED_SHORT_5_6_5)
- {
- chosenDUI = dui;
- }
- break;
-
- default:
- break;
- }
-
- if (!chosenDUI)
- return false;
-
- gfx::DataSourceSurface::ScopedMap map(surf, gfx::DataSourceSurface::MapType::READ);
- if (!map.IsMapped())
- return false;
-
- const webgl::PackingInfo pi = {chosenDUI->unpackFormat, chosenDUI->unpackType};
- const auto bytesPerPixel = webgl::BytesPerPixel(pi);
- const size_t bytesPerRow = width * bytesPerPixel;
-
- const GLint kMaxUnpackAlignment = 8;
- size_t unpackAlignment;
- if (!GuessAlignment(map.GetData(), bytesPerRow, map.GetStride(), kMaxUnpackAlignment,
- &unpackAlignment))
- {
- return false;
- // TODO: Consider using UNPACK_ settings to set the stride based on the too-large
- // alignment used for some SourceSurfaces. (D2D allegedy likes alignment=16)
- }
-
- MOZ_ALWAYS_TRUE( webgl->gl->MakeCurrent() );
- ScopedUnpackReset scopedReset(webgl);
- gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, unpackAlignment);
-
- const GLsizei depth = 1;
- GLenum error = DoTexOrSubImage(isSubImage, gl, target.get(), level, chosenDUI,
- xOffset, yOffset, zOffset, width, height, depth,
- map.GetData());
- if (error) {
- *out_glError = error;
- return false;
- }
-
- return true;
-}
-
-////////////////////
-
-static bool
-GetFormatForSurf(gfx::SourceSurface* surf, WebGLTexelFormat* const out_texelFormat)
-{
- gfx::SurfaceFormat surfFormat = surf->GetFormat();
-
+ const auto surfFormat = surf->GetFormat();
switch (surfFormat) {
case gfx::SurfaceFormat::B8G8R8A8:
*out_texelFormat = WebGLTexelFormat::BGRA8;
+ *out_bpp = 4;
return true;
case gfx::SurfaceFormat::B8G8R8X8:
*out_texelFormat = WebGLTexelFormat::BGRX8;
+ *out_bpp = 4;
return true;
case gfx::SurfaceFormat::R8G8B8A8:
*out_texelFormat = WebGLTexelFormat::RGBA8;
+ *out_bpp = 4;
return true;
case gfx::SurfaceFormat::R8G8B8X8:
*out_texelFormat = WebGLTexelFormat::RGBX8;
+ *out_bpp = 4;
return true;
case gfx::SurfaceFormat::R5G6B5_UINT16:
*out_texelFormat = WebGLTexelFormat::RGB565;
+ *out_bpp = 2;
return true;
case gfx::SurfaceFormat::A8:
*out_texelFormat = WebGLTexelFormat::A8;
+ *out_bpp = 1;
return true;
case gfx::SurfaceFormat::YUV:
// Ugh...
NS_ERROR("We don't handle uploads from YUV sources yet.");
// When we want to, check out gfx/ycbcr/YCbCrUtils.h. (specifically
// GetYCbCrToRGBDestFormatAndSize and ConvertYCbCrToRGB)
return false;
default:
return false;
}
}
-static bool
-GetFormatForPackingTuple(GLenum packingFormat, GLenum packingType,
- WebGLTexelFormat* const out_texelFormat)
-{
- switch (packingType) {
- case LOCAL_GL_UNSIGNED_BYTE:
- switch (packingFormat) {
- case LOCAL_GL_RED:
- case LOCAL_GL_LUMINANCE:
- case LOCAL_GL_RED_INTEGER:
- *out_texelFormat = WebGLTexelFormat::R8;
- return true;
-
- case LOCAL_GL_ALPHA:
- *out_texelFormat = WebGLTexelFormat::A8;
- return true;
-
- case LOCAL_GL_LUMINANCE_ALPHA:
- *out_texelFormat = WebGLTexelFormat::RA8;
- return true;
-
- case LOCAL_GL_RGB:
- case LOCAL_GL_RGB_INTEGER:
- *out_texelFormat = WebGLTexelFormat::RGB8;
- return true;
-
- case LOCAL_GL_RGBA:
- case LOCAL_GL_RGBA_INTEGER:
- *out_texelFormat = WebGLTexelFormat::RGBA8;
- return true;
-
- case LOCAL_GL_RG:
- case LOCAL_GL_RG_INTEGER:
- *out_texelFormat = WebGLTexelFormat::RG8;
- return true;
-
- default:
- break;
- }
- break;
-
- case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
- switch (packingFormat) {
- case LOCAL_GL_RGB:
- *out_texelFormat = WebGLTexelFormat::RGB565;
- return true;
-
- default:
- break;
- }
- break;
-
- case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
- switch (packingFormat) {
- case LOCAL_GL_RGBA:
- *out_texelFormat = WebGLTexelFormat::RGBA5551;
- return true;
-
- default:
- break;
- }
- break;
-
- case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
- switch (packingFormat) {
- case LOCAL_GL_RGBA:
- *out_texelFormat = WebGLTexelFormat::RGBA4444;
- return true;
-
- default:
- break;
- }
- break;
-
- case LOCAL_GL_HALF_FLOAT:
- case LOCAL_GL_HALF_FLOAT_OES:
- switch (packingFormat) {
- case LOCAL_GL_RED:
- case LOCAL_GL_LUMINANCE:
- *out_texelFormat = WebGLTexelFormat::R16F;
- return true;
-
- case LOCAL_GL_ALPHA:
- *out_texelFormat = WebGLTexelFormat::A16F;
- return true;
-
- case LOCAL_GL_LUMINANCE_ALPHA:
- *out_texelFormat = WebGLTexelFormat::RA16F;
- return true;
-
- case LOCAL_GL_RGB:
- *out_texelFormat = WebGLTexelFormat::RGB16F;
- return true;
-
- case LOCAL_GL_RGBA:
- *out_texelFormat = WebGLTexelFormat::RGBA16F;
- return true;
-
- case LOCAL_GL_RG:
- *out_texelFormat = WebGLTexelFormat::RG16F;
- return true;
-
- default:
- break;
- }
- break;
-
- case LOCAL_GL_FLOAT:
- switch (packingFormat) {
- case LOCAL_GL_RED:
- case LOCAL_GL_LUMINANCE:
- *out_texelFormat = WebGLTexelFormat::R32F;
- return true;
-
- case LOCAL_GL_ALPHA:
- *out_texelFormat = WebGLTexelFormat::A32F;
- return true;
-
- case LOCAL_GL_LUMINANCE_ALPHA:
- *out_texelFormat = WebGLTexelFormat::RA32F;
- return true;
-
- case LOCAL_GL_RGB:
- *out_texelFormat = WebGLTexelFormat::RGB32F;
- return true;
-
- case LOCAL_GL_RGBA:
- *out_texelFormat = WebGLTexelFormat::RGBA32F;
- return true;
-
- case LOCAL_GL_RG:
- *out_texelFormat = WebGLTexelFormat::RG32F;
- return true;
-
- default:
- break;
- }
- break;
-
- case LOCAL_GL_UNSIGNED_INT_10F_11F_11F_REV:
- switch (packingFormat) {
- case LOCAL_GL_RGB:
- *out_texelFormat = WebGLTexelFormat::RGB11F11F10F;
- return true;
-
- default:
- break;
- }
- break;
- default:
- break;
- }
-
- NS_ERROR("Unsupported EffectiveFormat dest format for DOM element upload.");
- return false;
-}
-
-/*static*/ bool
-TexUnpackSurface::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)
-{
- *out_outOfMemory = false;
-
- const size_t width = surf->GetSize().width;
- const size_t height = surf->GetSize().height;
-
- // Source args:
-
- // After we call this, on OSX, our GLContext will no longer be current.
- gfx::DataSourceSurface::ScopedMap srcMap(surf, gfx::DataSourceSurface::MapType::READ);
- if (!srcMap.IsMapped())
- return false;
-
- const void* const srcBegin = srcMap.GetData();
- const size_t srcStride = srcMap.GetStride();
-
- WebGLTexelFormat srcFormat;
- if (!GetFormatForSurf(surf, &srcFormat))
- return false;
-
- const bool srcPremultiplied = isSurfAlphaPremult;
-
- // Dest args:
-
- WebGLTexelFormat dstFormat;
- if (!GetFormatForPackingTuple(dui->unpackFormat, dui->unpackType, &dstFormat))
- return false;
-
- const auto bytesPerPixel = webgl::BytesPerPixel({dui->unpackFormat, dui->unpackType});
- const size_t dstRowBytes = bytesPerPixel * width;
-
- const size_t dstAlignment = 8; // Just use the max!
- const size_t dstStride = RoundUpToMultipleOf(dstRowBytes, dstAlignment);
-
- CheckedUint32 checkedDstSize = dstStride;
- checkedDstSize *= height;
- if (!checkedDstSize.isValid()) {
- *out_outOfMemory = true;
- return false;
- }
-
- const size_t dstSize = checkedDstSize.value();
-
- UniqueBuffer dstBuffer = malloc(dstSize);
- if (!dstBuffer) {
- *out_outOfMemory = true;
- return false;
- }
- void* const dstBegin = dstBuffer.get();
-
- gl::OriginPos srcOrigin, dstOrigin;
- OriginsForDOM(webgl, &srcOrigin, &dstOrigin);
-
- const bool dstPremultiplied = webgl->mPixelStore_PremultiplyAlpha;
-
- // And go!:
- bool wasTrivial;
- if (!ConvertImage(width, height,
- srcBegin, srcStride, srcOrigin, srcFormat, srcPremultiplied,
- dstBegin, dstStride, dstOrigin, dstFormat, dstPremultiplied,
- &wasTrivial))
- {
- MOZ_ASSERT(false, "ConvertImage failed unexpectedly.");
- NS_ERROR("ConvertImage failed unexpectedly.");
- *out_outOfMemory = true;
- return false;
- }
-
- *out_convertedBuffer = Move(dstBuffer);
- *out_convertedAlignment = dstAlignment;
- *out_wasTrivial = wasTrivial;
- return true;
-}
-
-
-////////////////////
+//////////
bool
TexUnpackSurface::TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
WebGLTexture* tex, TexImageTarget target, GLint level,
- const webgl::DriverUnpackInfo* dui, GLint xOffset,
+ const webgl::DriverUnpackInfo* dstDUI, GLint xOffset,
GLint yOffset, GLint zOffset,
GLenum* const out_error) const
{
WebGLContext* webgl = tex->mContext;
- // MakeCurrent is a big mess in here, because mapping (and presumably unmapping) on
- // OSX can lose our MakeCurrent. Therefore it's easiest to MakeCurrent just before we
- // call into GL, instead of trying to keep MakeCurrent-ed.
-
- RefPtr<gfx::DataSourceSurface> dataSurf = mSurf->GetDataSurface();
- if (!dataSurf) {
- // Since GetDataSurface didn't return error code, assume system
- // is out of memory
- webgl->ErrorOutOfMemory("%s: OOM in GetDataSurface for TexUnpackSurface.",
- funcName);
+ WebGLTexelFormat srcFormat;
+ uint8_t srcBPP;
+ if (!GetFormatForSurf(mSurf, &srcFormat, &srcBPP)) {
+ webgl->ErrorImplementationBug("%s: GetFormatForSurf failed for"
+ " WebGLTexelFormat::%u.",
+ funcName, uint32_t(mSurf->GetFormat()));
return false;
}
- if (UploadDataSurface(isSubImage, webgl, target, level, dui, xOffset, yOffset,
- zOffset, mWidth, mHeight, dataSurf, mIsAlphaPremult, out_error))
- {
- return true;
- }
+ gfx::DataSourceSurface::ScopedMap map(mSurf, gfx::DataSourceSurface::MapType::READ);
+ if (!map.IsMapped())
+ return false;
+
+ const auto srcBytes = map.GetData();
+ const auto srcStride = map.GetStride();
// CPU conversion. (++numCopies)
- UniqueBuffer convertedBuffer;
- uint8_t convertedAlignment;
- bool wasTrivial;
- bool outOfMemory;
- if (!ConvertSurface(webgl, dui, dataSurf, mIsAlphaPremult, &convertedBuffer,
- &convertedAlignment, &wasTrivial, &outOfMemory))
+ webgl->GenerateWarning("%s: Incurred CPU-side conversion, which is very slow.",
+ funcName);
+
+ const void* uploadBytes;
+ UniqueBuffer tempBuffer;
+ if (!ConvertIfNeeded(webgl, funcName, srcBytes, srcStride, srcBPP, srcFormat,
+ dstDUI, &uploadBytes, &tempBuffer))
{
- webgl->ErrorOutOfMemory("%s: %s in ConvertSurface for TexUnpackSurface.",
- funcName, outOfMemory ? "OOM" : "Failure");
return false;
}
- if (!wasTrivial) {
- webgl->GenerateWarning("%s: Chosen format/type incured an expensive reformat:"
- " 0x%04x/0x%04x",
- funcName, dui->unpackFormat, dui->unpackType);
- }
+ //////
+
+ gl::GLContext* const gl = webgl->gl;
+ MOZ_ALWAYS_TRUE( gl->MakeCurrent() );
- MOZ_ALWAYS_TRUE( webgl->gl->MakeCurrent() );
- ScopedUnpackReset scopedReset(webgl);
- webgl->gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, convertedAlignment);
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, mRowLength);
- *out_error = DoTexOrSubImage(isSubImage, webgl->gl, target.get(), level, dui, xOffset,
- yOffset, zOffset, mWidth, mHeight, mDepth,
- convertedBuffer.get());
+ *out_error = DoTexOrSubImage(isSubImage, gl, target.get(), level, dstDUI, xOffset,
+ yOffset, zOffset, mWidth, mHeight, mDepth, uploadBytes);
+
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, webgl->mPixelStore_UnpackRowLength);
+
return true;
}
} // namespace webgl
} // namespace mozilla
--- a/dom/canvas/TexUnpackBlob.h
+++ b/dom/canvas/TexUnpackBlob.h
@@ -4,16 +4,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef TEX_UNPACK_BLOB_H_
#define TEX_UNPACK_BLOB_H_
#include "GLContextTypes.h"
#include "GLTypes.h"
#include "WebGLStrongTypes.h"
+#include "WebGLTypes.h"
template <class T>
class RefPtr;
namespace mozilla {
class UniqueBuffer;
@@ -51,94 +52,87 @@ 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;
+ const bool mIsSrcPremult;
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);
+ TexUnpackBlob(const WebGLContext* webgl, TexImageTarget target, uint32_t rowLength,
+ uint32_t width, uint32_t height, uint32_t depth, bool isSrcPremult);
public:
virtual ~TexUnpackBlob() { }
+protected:
+ bool ConvertIfNeeded(WebGLContext* webgl, const char* funcName, const void* srcBytes,
+ uint32_t srcStride, uint8_t srcBPP, WebGLTexelFormat srcFormat,
+ const webgl::DriverUnpackInfo* dstDUI,
+ const void** const out_bytes,
+ UniqueBuffer* const out_anchoredBuffer) const;
+
+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);
+ WebGLTexture* tex, TexImageTarget target, GLint level,
+ const webgl::DriverUnpackInfo* dui, GLint xOffset,
+ GLint yOffset, GLint zOffset,
+ GLenum* const out_error) const = 0;
};
-class TexUnpackBytes : public TexUnpackBlob
+class TexUnpackBytes final : public TexUnpackBlob
{
public:
const void* const mBytes;
- TexUnpackBytes(const WebGLContext* webgl, uint32_t width, uint32_t height,
- uint32_t depth, const void* bytes);
+ TexUnpackBytes(const WebGLContext* webgl, TexImageTarget target, uint32_t width,
+ uint32_t height, uint32_t depth, const void* bytes);
+
+ virtual bool HasData() const override { return bool(mBytes); }
+
+ 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;
+};
+
+class TexUnpackImage final : public TexUnpackBlob
+{
+public:
+ const RefPtr<layers::Image> mImage;
+
+ TexUnpackImage(const WebGLContext* webgl, TexImageTarget target, uint32_t width,
+ uint32_t height, uint32_t depth, 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;
+};
+
+class TexUnpackSurface final : public TexUnpackBlob
+{
+public:
+ const RefPtr<gfx::DataSourceSurface> mSurf;
+
+ TexUnpackSurface(const WebGLContext* webgl, TexImageTarget target, uint32_t width,
+ uint32_t height, uint32_t depth, gfx::DataSourceSurface* 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;
};
-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;
-};
-
-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;
-
-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,
- TexImageTarget target, GLint level,
- const webgl::DriverUnpackInfo* dui, GLint xOffset,
- GLint yOffset, GLint zOffset, GLsizei width,
- GLsizei height, gfx::DataSourceSurface* surf,
- bool isSurfAlphaPremult, GLenum* const out_glError);
-};
-
} // namespace webgl
} // namespace mozilla
#endif // TEX_UNPACK_BLOB_H_
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -283,16 +283,17 @@ public:
void ErrorInvalidEnum(const char* fmt = 0, ...);
void ErrorInvalidOperation(const char* fmt = 0, ...);
void ErrorInvalidValue(const char* fmt = 0, ...);
void ErrorInvalidFramebufferOperation(const char* fmt = 0, ...);
void ErrorInvalidEnumInfo(const char* info, GLenum enumValue);
void ErrorInvalidEnumInfo(const char* info, const char* funcName,
GLenum enumValue);
void ErrorOutOfMemory(const char* fmt = 0, ...);
+ void ErrorImplementationBug(const char* fmt = 0, ...);
const char* ErrorName(GLenum error);
/**
* Return displayable name for GLenum.
* This version is like gl::GLenumToStr but with out the GL_ prefix to
* keep consistency with how errors are reported from WebGL.
*/
@@ -958,20 +959,16 @@ protected:
bool ValidateTexImageSelection(const char* funcName, uint8_t funcDims,
GLenum texImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLint zOffset, GLsizei width,
GLsizei height, GLsizei depth,
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);
// -----------------------------------------------------------------------------
// Vertices Feature (WebGLContextVertices.cpp)
public:
void DrawArrays(GLenum mode, GLint first, GLsizei count);
void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count,
@@ -1328,34 +1325,18 @@ protected:
// helpers
bool ConvertImage(size_t width, size_t height, size_t srcStride,
size_t dstStride, const uint8_t* src, uint8_t* dst,
WebGLTexelFormat srcFormat, bool srcPremultiplied,
WebGLTexelFormat dstFormat, bool dstPremultiplied,
size_t dstTexelSize);
-public:
- nsLayoutUtils::SurfaceFromElementResult
- SurfaceFromElement(dom::Element* elem)
- {
- uint32_t flags = nsLayoutUtils::SFE_WANT_IMAGE_SURFACE |
- nsLayoutUtils::SFE_USE_ELEMENT_SIZE_IF_VECTOR;
+ //////
- if (mPixelStore_ColorspaceConversion == LOCAL_GL_NONE)
- flags |= nsLayoutUtils::SFE_NO_COLORSPACE_CONVERSION;
-
- if (!mPixelStore_PremultiplyAlpha)
- flags |= nsLayoutUtils::SFE_PREFER_NO_PREMULTIPLY_ALPHA;
-
- RefPtr<gfx::DrawTarget> idealDrawTarget = nullptr; // Don't care for now.
- return nsLayoutUtils::SurfaceFromElement(elem, flags, idealDrawTarget);
- }
-
-protected:
// Returns false if `object` is null or not valid.
template<class ObjectType>
bool ValidateObject(const char* info, ObjectType* object);
// Returns false if `object` is not valid. Considers null to be valid.
template<class ObjectType>
bool ValidateObjectAllowNull(const char* info, ObjectType* object);
@@ -1623,16 +1604,17 @@ public:
CreateFormatUsage(gl::GLContext* gl) const = 0;
// Friend list
friend class ScopedCopyTexImageSource;
friend class ScopedResolveTexturesForDraw;
friend class ScopedUnpackReset;
friend class webgl::TexUnpackBlob;
friend class webgl::TexUnpackBytes;
+ friend class webgl::TexUnpackImage;
friend class webgl::TexUnpackSurface;
friend class WebGLTexture;
friend class WebGLFBAttachPoint;
friend class WebGLFramebuffer;
friend class WebGLRenderbuffer;
friend class WebGLProgram;
friend class WebGLQuery;
friend class WebGLBuffer;
--- a/dom/canvas/WebGLContextUtils.cpp
+++ b/dom/canvas/WebGLContextUtils.cpp
@@ -1,13 +1,14 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "WebGLContextUtils.h"
#include "WebGLContext.h"
#include "GLContext.h"
#include "jsapi.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/Preferences.h"
#include "nsIDOMDataContainerEvent.h"
#include "nsIDOMEvent.h"
@@ -18,17 +19,16 @@
#include "prprf.h"
#include <stdarg.h>
#include "WebGLBuffer.h"
#include "WebGLExtensions.h"
#include "WebGLFramebuffer.h"
#include "WebGLProgram.h"
#include "WebGLTexture.h"
#include "WebGLVertexArray.h"
-#include "WebGLContextUtils.h"
namespace mozilla {
TexTarget
TexImageTargetToTexTarget(TexImageTarget texImageTarget)
{
switch (texImageTarget.get()) {
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
@@ -202,16 +202,32 @@ WebGLContext::ErrorOutOfMemory(const cha
va_list va;
va_start(va, fmt);
GenerateWarning(fmt, va);
va_end(va);
return SynthesizeGLError(LOCAL_GL_OUT_OF_MEMORY);
}
+void
+WebGLContext::ErrorImplementationBug(const char* fmt, ...)
+{
+ const nsPrintfCString warning("Implementation bug, please file at %s! %s",
+ "https://bugzilla.mozilla.org/", fmt);
+
+ va_list va;
+ va_start(va, fmt);
+ GenerateWarning(warning.BeginReading(), va);
+ va_end(va);
+
+ MOZ_ASSERT(false, "WebGLContext::ErrorImplementationBug");
+ NS_ERROR("WebGLContext::ErrorImplementationBug");
+ return SynthesizeGLError(LOCAL_GL_OUT_OF_MEMORY);
+}
+
const char*
WebGLContext::ErrorName(GLenum error)
{
switch(error) {
case LOCAL_GL_INVALID_ENUM:
return "INVALID_ENUM";
case LOCAL_GL_INVALID_OPERATION:
return "INVALID_OPERATION";
--- a/dom/canvas/WebGLTexture.h
+++ b/dom/canvas/WebGLTexture.h
@@ -407,16 +407,19 @@ TexImageTargetForTargetAndFace(TexTarget
default:
MOZ_CRASH("GFX: TexImageTargetForTargetAndFace");
}
}
already_AddRefed<mozilla::layers::Image>
ImageFromVideo(dom::HTMLVideoElement* elem);
+bool
+IsTarget3D(TexImageTarget target);
+
GLenum
DoTexImage(gl::GLContext* gl, TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLsizei width, GLsizei height,
GLsizei depth, const void* data);
GLenum
DoTexSubImage(gl::GLContext* gl, TexImageTarget target, GLint level, GLint xOffset,
GLint yOffset, GLint zOffset, GLsizei width, GLsizei height,
GLsizei depth, const webgl::PackingInfo& pi, const void* data);
--- a/dom/canvas/WebGLTextureUpload.cpp
+++ b/dom/canvas/WebGLTextureUpload.cpp
@@ -173,21 +173,22 @@ WebGLContext::ValidateUnpackPixels(const
" 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,
+BlobFromView(WebGLContext* webgl, const char* funcName, TexImageTarget target,
+ uint32_t width, uint32_t height, uint32_t depth,
+ const webgl::PackingInfo& pi,
const dom::Nullable<dom::ArrayBufferView>& maybeView)
{
- const void* bytes = nullptr;
+ const uint8_t* 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`.",
@@ -198,18 +199,18 @@ BlobFromView(WebGLContext* webgl, const
if (width && height && depth) {
view.ComputeLengthAndData();
bytes = view.DataAllowShared();
byteCount = view.LengthAllowShared();
}
}
- UniquePtr<webgl::TexUnpackBlob> blob(new webgl::TexUnpackBytes(webgl, width, height,
- depth, bytes));
+ UniquePtr<webgl::TexUnpackBlob> blob(new webgl::TexUnpackBytes(webgl, target, width,
+ height, depth, bytes));
//////
if (bytes) {
const auto bytesPerPixel = webgl::BytesPerPixel(pi);
const auto bytesPerRow = CheckedUint32(blob->mRowLength) * bytesPerPixel;
const auto rowStride = RoundUpToMultipleOf(bytesPerRow, blob->mAlignment);
@@ -263,29 +264,29 @@ WebGLTexture::TexOrSubImage(bool isSubIm
{
return;
}
webgl::PackingInfo pi;
if (!mContext->ValidateUnpackInfo(funcName, unpackFormat, unpackType, &pi))
return;
- const auto blob = BlobFromView(mContext, funcName, width, height, depth, pi,
+ const auto blob = BlobFromView(mContext, funcName, target, width, height, depth, pi,
maybeView);
if (!blob)
return;
TexOrSubImageBlob(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, pi, blob.get());
}
////////////////////////////////////////
// ImageData
-static already_AddRefed<gfx::SourceSurface>
+static already_AddRefed<gfx::DataSourceSurface>
FromImageData(WebGLContext* webgl, const char* funcName, GLenum unpackType,
dom::ImageData* imageData, dom::Uint8ClampedArray* scopedArr)
{
DebugOnly<bool> inited = scopedArr->Init(imageData->GetDataObject());
MOZ_ASSERT(inited);
scopedArr->ComputeLengthAndData();
const DebugOnly<size_t> dataSize = scopedArr->Length();
@@ -294,58 +295,29 @@ FromImageData(WebGLContext* webgl, const
const gfx::IntSize size(imageData->Width(), imageData->Height());
const size_t stride = size.width * 4;
const gfx::SurfaceFormat surfFormat = gfx::SurfaceFormat::R8G8B8A8;
MOZ_ASSERT(dataSize == stride * size.height);
uint8_t* wrappableData = (uint8_t*)data;
- RefPtr<gfx::SourceSurface> surf =
+ 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();
}
-bool
-WebGLContext::GetUnpackValuesForImage(const char* funcName, uint32_t srcImageWidth,
- uint32_t srcImageHeight,
- uint32_t* const out_rowLength,
- uint32_t* const out_imageHeight)
-{
- uint32_t rowLength = mPixelStore_UnpackRowLength;
- if (!rowLength) {
- rowLength = srcImageWidth;
- } else if (rowLength != srcImageWidth) {
- ErrorInvalidOperation("%s: UNPACK_ROW_LENGTH, if set, must be == width of"
- " object.");
- return false;
- }
-
- uint32_t imageHeight = mPixelStore_UnpackImageHeight;
- if (!imageHeight) {
- imageHeight = srcImageHeight;
- } else if (imageHeight > srcImageHeight) {
- ErrorInvalidOperation("%s: UNPACK_IMAGE_HEIGHT, if set, must be <= height of"
- " object");
- return false;
- }
-
- *out_rowLength = rowLength;
- *out_imageHeight = imageHeight;
- return true;
-}
-
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)
{
webgl::PackingInfo pi;
if (!mContext->ValidateUnpackInfo(funcName, unpackFormat, unpackType, &pi))
@@ -357,37 +329,30 @@ WebGLTexture::TexOrSubImage(bool isSubIm
return;
}
// Eventually, these will be args.
const uint32_t width = imageData->Width();
const uint32_t height = imageData->Height();
const uint32_t depth = 1;
- uint32_t rowLength, imageHeight;
- if (!mContext->GetUnpackValuesForImage(funcName, imageData->Width(),
- imageData->Height(), &rowLength, &imageHeight))
- {
- return;
- }
-
- dom::RootedTypedArray<dom::Uint8ClampedArray> scopedArr(
- nsContentUtils::RootingCx());
- const RefPtr<gfx::SourceSurface> surf = FromImageData(mContext, funcName, unpackType,
- imageData, &scopedArr);
+ dom::RootedTypedArray<dom::Uint8ClampedArray> scopedArr(nsContentUtils::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 surfIsAlphaPremult = false;
+ const bool isAlphaPremult = false;
- const webgl::TexUnpackSurface blob(mContext, imageHeight, width, height, depth, surf,
- surfIsAlphaPremult);
+ const 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);
@@ -402,51 +367,71 @@ WebGLTexture::TexOrSubImage(bool isSubIm
GLint yOffset, GLint zOffset, GLenum unpackFormat,
GLenum unpackType, dom::Element* elem,
ErrorResult* const out_error)
{
webgl::PackingInfo pi;
if (!mContext->ValidateUnpackInfo(funcName, unpackFormat, unpackType, &pi))
return;
- auto sfer = mContext->SurfaceFromElement(elem);
+ //////
+
+ uint32_t flags = nsLayoutUtils::SFE_WANT_IMAGE_SURFACE |
+ nsLayoutUtils::SFE_USE_ELEMENT_SIZE_IF_VECTOR;
+
+ if (mContext->mPixelStore_ColorspaceConversion == LOCAL_GL_NONE)
+ flags |= nsLayoutUtils::SFE_NO_COLORSPACE_CONVERSION;
+
+ if (!mContext->mPixelStore_PremultiplyAlpha)
+ flags |= nsLayoutUtils::SFE_PREFER_NO_PREMULTIPLY_ALPHA;
+
+ RefPtr<gfx::DrawTarget> idealDrawTarget = nullptr; // Don't care for now.
+ auto sfer = nsLayoutUtils::SurfaceFromElement(elem, flags, idealDrawTarget);
+
+ //////
uint32_t elemWidth = 0;
uint32_t elemHeight = 0;
layers::Image* layersImage = nullptr;
if (!gfxPrefs::WebGLDisableDOMBlitUploads() && sfer.mLayersImage) {
layersImage = sfer.mLayersImage;
elemWidth = layersImage->GetSize().width;
elemHeight = layersImage->GetSize().height;
}
- gfx::SourceSurface* surf = nullptr;
+ RefPtr<gfx::DataSourceSurface> dataSurf;
if (!layersImage && sfer.GetSourceSurface()) {
- surf = sfer.GetSourceSurface();
+ const auto surf = sfer.GetSourceSurface();
elemWidth = surf->GetSize().width;
elemHeight = surf->GetSize().height;
+
+ // WARNING: OSX can lose our MakeCurrent here.
+ dataSurf = surf->GetDataSurface();
}
+ //////
+
// Eventually, these will be args.
const uint32_t width = elemWidth;
const uint32_t height = elemHeight;
const uint32_t depth = 1;
- // 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);
+ if (!layersImage && !dataSurf) {
+ const webgl::TexUnpackBytes blob(mContext, target, width, height, depth, nullptr);
TexOrSubImageBlob(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, pi, &blob);
return;
}
//////
+ // 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 (!sfer.mCORSUsed) {
auto& srcPrincipal = sfer.mPrincipal;
nsIPrincipal* dstPrincipal = mContext->GetCanvas()->NodePrincipal();
if (!dstPrincipal->Subsumes(srcPrincipal)) {
mContext->GenerateWarning("%s: Cross-origin elements require CORS.",
funcName);
out_error->Throw(NS_ERROR_DOM_SECURITY_ERR);
@@ -463,33 +448,26 @@ WebGLTexture::TexOrSubImage(bool isSubIm
funcName);
out_error->Throw(NS_ERROR_DOM_SECURITY_ERR);
return;
}
//////
// Ok, we're good!
- uint32_t rowLength, imageHeight;
- if (!mContext->GetUnpackValuesForImage(funcName, elemWidth, elemHeight, &rowLength,
- &imageHeight))
- {
- return;
- }
-
UniquePtr<const webgl::TexUnpackBlob> blob;
const bool isAlphaPremult = sfer.mIsPremultiplied;
if (layersImage) {
- blob.reset(new webgl::TexUnpackImage(mContext, imageHeight, width, height, depth,
+ blob.reset(new webgl::TexUnpackImage(mContext, target, width, height, depth,
layersImage, isAlphaPremult));
} else {
- MOZ_ASSERT(surf);
- blob.reset(new webgl::TexUnpackSurface(mContext, imageHeight, width, height,
- depth, surf, isAlphaPremult));
+ MOZ_ASSERT(dataSurf);
+ blob.reset(new webgl::TexUnpackSurface(mContext, target, width, height, depth,
+ dataSurf, 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,
@@ -831,18 +809,18 @@ DoTexStorage(gl::GLContext* gl, TexTarge
default:
MOZ_CRASH("GFX: bad target");
}
return errorScope.GetError();
}
-static bool
-Is3D(TexImageTarget target)
+bool
+IsTarget3D(TexImageTarget target)
{
switch (target.get()) {
case LOCAL_GL_TEXTURE_2D:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
@@ -862,17 +840,17 @@ GLenum
DoTexImage(gl::GLContext* gl, TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLsizei width, GLsizei height,
GLsizei depth, const void* data)
{
const GLint border = 0;
gl::GLContext::LocalErrorScope errorScope(*gl);
- if (Is3D(target)) {
+ if (IsTarget3D(target)) {
gl->fTexImage3D(target.get(), level, dui->internalFormat, width, height, depth,
border, dui->unpackFormat, dui->unpackType, data);
} else {
MOZ_ASSERT(depth == 1);
gl->fTexImage2D(target.get(), level, dui->internalFormat, width, height, border,
dui->unpackFormat, dui->unpackType, data);
}
@@ -881,17 +859,17 @@ DoTexImage(gl::GLContext* gl, TexImageTa
GLenum
DoTexSubImage(gl::GLContext* gl, TexImageTarget target, GLint level, GLint xOffset,
GLint yOffset, GLint zOffset, GLsizei width, GLsizei height, GLsizei depth,
const webgl::PackingInfo& pi, const void* data)
{
gl::GLContext::LocalErrorScope errorScope(*gl);
- if (Is3D(target)) {
+ if (IsTarget3D(target)) {
gl->fTexSubImage3D(target.get(), level, xOffset, yOffset, zOffset, width, height,
depth, pi.format, pi.type, data);
} else {
MOZ_ASSERT(zOffset == 0);
MOZ_ASSERT(depth == 1);
gl->fTexSubImage2D(target.get(), level, xOffset, yOffset, width, height,
pi.format, pi.type, data);
}
@@ -903,17 +881,17 @@ static inline GLenum
DoCompressedTexImage(gl::GLContext* gl, TexImageTarget target, GLint level,
GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth,
GLsizei dataSize, const void* data)
{
const GLint border = 0;
gl::GLContext::LocalErrorScope errorScope(*gl);
- if (Is3D(target)) {
+ if (IsTarget3D(target)) {
gl->fCompressedTexImage3D(target.get(), level, internalFormat, width, height,
depth, border, dataSize, data);
} else {
MOZ_ASSERT(depth == 1);
gl->fCompressedTexImage2D(target.get(), level, internalFormat, width, height,
border, dataSize, data);
}
@@ -923,17 +901,17 @@ DoCompressedTexImage(gl::GLContext* gl,
GLenum
DoCompressedTexSubImage(gl::GLContext* gl, TexImageTarget target, GLint level,
GLint xOffset, GLint yOffset, GLint zOffset, GLsizei width,
GLsizei height, GLsizei depth, GLenum sizedUnpackFormat,
GLsizei dataSize, const void* data)
{
gl::GLContext::LocalErrorScope errorScope(*gl);
- if (Is3D(target)) {
+ if (IsTarget3D(target)) {
gl->fCompressedTexSubImage3D(target.get(), level, xOffset, yOffset, zOffset,
width, height, depth, sizedUnpackFormat, dataSize,
data);
} else {
MOZ_ASSERT(zOffset == 0);
MOZ_ASSERT(depth == 1);
gl->fCompressedTexSubImage2D(target.get(), level, xOffset, yOffset, width,
height, sizedUnpackFormat, dataSize, data);
@@ -945,31 +923,31 @@ DoCompressedTexSubImage(gl::GLContext* g
static inline GLenum
DoCopyTexImage2D(gl::GLContext* gl, TexImageTarget target, GLint level,
GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height)
{
const GLint border = 0;
gl::GLContext::LocalErrorScope errorScope(*gl);
- MOZ_ASSERT(!Is3D(target));
+ MOZ_ASSERT(!IsTarget3D(target));
gl->fCopyTexImage2D(target.get(), level, internalFormat, x, y, width, height,
border);
return errorScope.GetError();
}
static inline GLenum
DoCopyTexSubImage(gl::GLContext* gl, TexImageTarget target, GLint level, GLint xOffset,
GLint yOffset, GLint zOffset, GLint x, GLint y, GLsizei width,
GLsizei height)
{
gl::GLContext::LocalErrorScope errorScope(*gl);
- if (Is3D(target)) {
+ if (IsTarget3D(target)) {
gl->fCopyTexSubImage3D(target.get(), level, xOffset, yOffset, zOffset, x, y,
width, height);
} else {
MOZ_ASSERT(zOffset == 0);
gl->fCopyTexSubImage2D(target.get(), level, xOffset, yOffset, x, y, width,
height);
}
@@ -1258,17 +1236,17 @@ WebGLTexture::TexImage(const char* funcN
// Check that source and dest info are compatible
auto dstFormat = dstUsage->format;
if (!ValidateTargetForFormat(funcName, mContext, target, dstFormat))
return;
if (!mContext->IsWebGL2() && dstFormat->hasDepth) {
if (target != LOCAL_GL_TEXTURE_2D ||
- blob->mHasData ||
+ blob->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;
}
@@ -1279,17 +1257,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);
+ blob->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;