--- a/dom/canvas/WebGLTextureUpload.cpp
+++ b/dom/canvas/WebGLTextureUpload.cpp
@@ -1925,16 +1925,87 @@ WebGLTexture::ValidateCopyTexImageForFee
" READ_BUFFER-selected COLOR_ATTACHMENT%u.",
funcName, attach->mAttachmentPoint);
return false;
}
}
return true;
}
+static bool
+DoCopyTexOrSubImage(WebGLContext* webgl, const char* funcName, bool isSubImage,
+ const WebGLTexture* tex, TexImageTarget target, GLint level,
+ GLint xWithinSrc, GLint yWithinSrc,
+ uint32_t srcTotalWidth, uint32_t srcTotalHeight,
+ const webgl::FormatUsageInfo* srcUsage,
+ GLint xOffset, GLint yOffset, GLint zOffset,
+ uint32_t dstWidth, uint32_t dstHeight,
+ const webgl::FormatUsageInfo* dstUsage)
+{
+ gl::GLContext* gl = webgl->gl;
+ gl->MakeCurrent();
+
+ ////
+
+ uint32_t readX, readY;
+ uint32_t writeX, writeY;
+ uint32_t rwWidth, rwHeight;
+ Intersect(srcTotalWidth, xWithinSrc, dstWidth, &readX, &writeX, &rwWidth);
+ Intersect(srcTotalHeight, yWithinSrc, dstHeight, &readY, &writeY, &rwHeight);
+
+ ////
+
+ GLenum error = 0;
+ do {
+ const auto& idealUnpack = dstUsage->idealUnpack;
+ if (!isSubImage) {
+ const auto& pi = idealUnpack->ToPacking();
+ const auto& bpp = BytesPerPixel(pi);
+ const UniqueBuffer zeros(calloc(1, dstWidth * dstHeight * bpp));
+ if (!zeros.get()) {
+ webgl->ErrorOutOfMemory("%s: Ran out of memory allocating zeros.",
+ funcName);
+ return false;
+ }
+ error = DoTexImage(gl, target, level, idealUnpack, dstWidth, dstHeight, 1,
+ zeros.get());
+ if (error)
+ break;
+ }
+
+ if (!rwWidth || !rwHeight) {
+ // There aren't any pixels to copy, so we're 'done'.
+ return true;
+ }
+
+ const auto& srcFormat = srcUsage->format;
+ ScopedCopyTexImageSource maybeSwizzle(webgl, funcName, srcTotalWidth,
+ srcTotalHeight, srcFormat, dstUsage);
+
+ const uint8_t zOffset = 0;
+ error = DoCopyTexSubImage(gl, target, level, writeX, writeY, zOffset, readX,
+ readY, rwWidth, rwHeight);
+ if (error)
+ break;
+
+ return true;
+ } while (false);
+
+ if (error == LOCAL_GL_OUT_OF_MEMORY) {
+ webgl->ErrorOutOfMemory("%s: Ran out of memory during texture copy.", funcName);
+ return false;
+ }
+
+ MOZ_RELEASE_ASSERT(false, "GFX: We should have caught all other errors.");
+ webgl->GenerateWarning("%s: Unexpected error during texture copy. Context lost.",
+ funcName);
+ webgl->ForceLoseContext();
+ return false;
+}
+
// There is no CopyTexImage3D.
void
WebGLTexture::CopyTexImage2D(TexImageTarget target, GLint level, GLenum internalFormat,
GLint x, GLint y, GLsizei rawWidth, GLsizei rawHeight,
GLint border)
{
const char funcName[] = "copyTexImage2D";
@@ -1955,107 +2026,57 @@ WebGLTexture::CopyTexImage2D(TexImageTar
return;
}
MOZ_ASSERT(imageInfo);
////////////////////////////////////
// Get source info
const webgl::FormatUsageInfo* srcUsage;
- uint32_t srcWidth;
- uint32_t srcHeight;
- if (!mContext->ValidateCurFBForRead(funcName, &srcUsage, &srcWidth, &srcHeight))
+ uint32_t srcTotalWidth;
+ uint32_t srcTotalHeight;
+ if (!mContext->ValidateCurFBForRead(funcName, &srcUsage, &srcTotalWidth,
+ &srcTotalHeight))
+ {
return;
- auto srcFormat = srcUsage->format;
+ }
if (!ValidateCopyTexImageForFeedback(funcName, level))
return;
////////////////////////////////////
// Check that source and dest info are compatible
+ const auto& srcFormat = srcUsage->format;
const auto dstUsage = ValidateCopyDestUsage(funcName, mContext, srcFormat,
internalFormat);
if (!dstUsage)
return;
- const auto dstFormat = dstUsage->format;
-
+ const auto& dstFormat = dstUsage->format;
if (!ValidateTargetForFormat(funcName, mContext, target, dstFormat))
return;
if (!mContext->IsWebGL2() && dstFormat->d) {
mContext->ErrorInvalidOperation("%s: Function may not be called with format %s.",
funcName, dstFormat->name);
return;
}
if (!ValidateCopyTexImageFormats(mContext, funcName, srcFormat, dstFormat))
return;
////////////////////////////////////
// Do the thing!
- gl::GLContext* gl = mContext->gl;
- gl->MakeCurrent();
-
- ScopedCopyTexImageSource maybeSwizzle(mContext, funcName, srcWidth, srcHeight,
- srcFormat, dstUsage);
-
- uint32_t readX, readY;
- uint32_t writeX, writeY;
- uint32_t rwWidth, rwHeight;
- Intersect(srcWidth, x, width, &readX, &writeX, &rwWidth);
- Intersect(srcHeight, y, height, &readY, &writeY, &rwHeight);
-
- const auto& idealUnpack = dstUsage->idealUnpack;
- const auto& driverInternalFormat = idealUnpack->internalFormat;
-
- GLenum error = DoCopyTexImage2D(gl, target, level, driverInternalFormat, x, y, width,
- height);
- do {
- if (rwWidth == uint32_t(width) && rwHeight == uint32_t(height))
- break;
-
- if (error)
- break;
-
- // 1. Zero the texture data.
- // 2. CopyTexSubImage the subrect.
-
- if (!ZeroTextureData(mContext, funcName, mGLName, target, level, dstUsage, width,
- height, depth))
- {
- mContext->ErrorOutOfMemory("%s: Failed to zero texture data.", funcName);
- MOZ_ASSERT(false, "Failed to zero texture data.");
- return;
- }
-
- if (!rwWidth || !rwHeight) {
- // There aren't any, so we're 'done'.
- mContext->DummyReadFramebufferOperation(funcName);
- return;
- }
-
- const uint8_t zOffset = 0;
- error = DoCopyTexSubImage(gl, target, level, writeX, writeY, zOffset, readX,
- readY, rwWidth, rwHeight);
- } while (false);
-
- if (error == LOCAL_GL_OUT_OF_MEMORY) {
- mContext->ErrorOutOfMemory("%s: Ran out of memory during texture copy.",
- funcName);
- return;
- }
- if (error) {
- MOZ_RELEASE_ASSERT(false, "GFX: We should have caught all other errors.");
- mContext->GenerateWarning("%s: Unexpected error during texture copy. Context"
- " lost.",
- funcName);
- mContext->ForceLoseContext();
+ const bool isSubImage = false;
+ if (!DoCopyTexOrSubImage(mContext, funcName, isSubImage, this, target, level, x, y,
+ srcTotalWidth, srcTotalHeight, srcUsage, 0, 0, 0, width,
+ height, dstUsage))
+ {
return;
}
////////////////////////////////////
// Update our specification data.
const bool isDataInitialized = true;
const ImageInfo newImageInfo(dstUsage, width, height, depth, isDataInitialized);
@@ -2082,87 +2103,63 @@ WebGLTexture::CopyTexSubImage(const char
width, height, depth, &imageInfo))
{
return;
}
MOZ_ASSERT(imageInfo);
auto dstUsage = imageInfo->mFormat;
MOZ_ASSERT(dstUsage);
+
auto dstFormat = dstUsage->format;
-
if (!mContext->IsWebGL2() && dstFormat->d) {
mContext->ErrorInvalidOperation("%s: Function may not be called on a texture of"
" format %s.",
funcName, dstFormat->name);
return;
}
////////////////////////////////////
// Get source info
const webgl::FormatUsageInfo* srcUsage;
- uint32_t srcWidth;
- uint32_t srcHeight;
- if (!mContext->ValidateCurFBForRead(funcName, &srcUsage, &srcWidth, &srcHeight))
+ uint32_t srcTotalWidth;
+ uint32_t srcTotalHeight;
+ if (!mContext->ValidateCurFBForRead(funcName, &srcUsage, &srcTotalWidth,
+ &srcTotalHeight))
+ {
return;
- auto srcFormat = srcUsage->format;
+ }
if (!ValidateCopyTexImageForFeedback(funcName, level, zOffset))
return;
////////////////////////////////////
// Check that source and dest info are compatible
+ auto srcFormat = srcUsage->format;
if (!ValidateCopyTexImageFormats(mContext, funcName, srcFormat, dstFormat))
return;
////////////////////////////////////
// Do the thing!
- mContext->gl->MakeCurrent();
-
- ScopedCopyTexImageSource maybeSwizzle(mContext, funcName, srcWidth, srcHeight,
- srcFormat, dstUsage);
-
- uint32_t readX, readY;
- uint32_t writeX, writeY;
- uint32_t rwWidth, rwHeight;
- Intersect(srcWidth, x, width, &readX, &writeX, &rwWidth);
- Intersect(srcHeight, y, height, &readY, &writeY, &rwHeight);
-
- if (!rwWidth || !rwHeight) {
- // There aren't any, so we're 'done'.
- mContext->DummyReadFramebufferOperation(funcName);
- return;
- }
-
bool uploadWillInitialize;
if (!EnsureImageDataInitializedForUpload(this, funcName, target, level, xOffset,
yOffset, zOffset, width, height, depth,
imageInfo, &uploadWillInitialize))
{
return;
}
- GLenum error = DoCopyTexSubImage(mContext->gl, target, level, xOffset + writeX,
- yOffset + writeY, zOffset, readX, readY, rwWidth,
- rwHeight);
-
- if (error == LOCAL_GL_OUT_OF_MEMORY) {
- mContext->ErrorOutOfMemory("%s: Ran out of memory during texture copy.",
- funcName);
- return;
- }
- if (error) {
- MOZ_RELEASE_ASSERT(false, "GFX: We should have caught all other errors.");
- mContext->GenerateWarning("%s: Unexpected error during texture copy. Context"
- " lost.",
- funcName);
- mContext->ForceLoseContext();
+ const bool isSubImage = true;
+ if (!DoCopyTexOrSubImage(mContext, funcName, isSubImage, this, target, level, x, y,
+ srcTotalWidth, srcTotalHeight, srcUsage, xOffset, yOffset,
+ zOffset, width, height, dstUsage))
+ {
return;
}
////////////////////////////////////
// Update our specification data?
if (uploadWillInitialize) {
imageInfo->SetIsDataInitialized(true, this);