Bug 1276093 - r?jrmuizel - Warn on slow CPU format conversions.
From 7778749a5a7a25e5e51dd70911a755a28e478db5 Mon Sep 17 00:00:00 2001
---
dom/canvas/TexUnpackBlob.cpp | 19 +++++++++++++++----
dom/canvas/TexUnpackBlob.h | 2 +-
dom/canvas/WebGLTexelConversions.cpp | 7 ++++++-
dom/canvas/WebGLTexelConversions.h | 3 ++-
4 files changed, 24 insertions(+), 7 deletions(-)
MozReview-Commit-ID: 7j38uPCeban
--- a/dom/canvas/TexUnpackBlob.cpp
+++ b/dom/canvas/TexUnpackBlob.cpp
@@ -213,20 +213,21 @@ TexUnpackBytes::TexOrSubImage(bool isSub
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, srcOrigin, texelFormat, srcPremultiplied,
tempBuffer.get(), rowStride, dstOrigin, texelFormat,
- dstPremultiplied))
+ dstPremultiplied, &unused_wasTrivial))
{
MOZ_ASSERT(false, "ConvertImage failed unexpectedly.");
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
return;
}
uploadBytes = tempBuffer.get();
} while (false);
@@ -657,17 +658,17 @@ GetFormatForPackingTuple(GLenum packingF
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_outOfMemory)
+ 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:
@@ -714,28 +715,31 @@ TexUnpackSurface::ConvertSurface(WebGLCo
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))
+ 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;
}
////////////////////
TexUnpackSurface::TexUnpackSurface(const RefPtr<gfx::SourceSurface>& surf,
bool isAlphaPremult)
@@ -780,29 +784,36 @@ TexUnpackSurface::TexOrSubImage(bool isS
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
return;
}
// CPU conversion. (++numCopies)
UniqueBuffer convertedBuffer;
uint8_t convertedAlignment;
+ bool wasTrivial;
bool outOfMemory;
if (!ConvertSurface(webgl, dui, dataSurf, mIsAlphaPremult, &convertedBuffer,
- &convertedAlignment, &outOfMemory))
+ &convertedAlignment, &wasTrivial, &outOfMemory))
{
if (outOfMemory) {
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
} else {
NS_ERROR("Failed to convert surface.");
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
}
return;
}
+ if (!wasTrivial) {
+ webgl->GenerateWarning("%s: Chosen format/type incured an expensive reformat:"
+ " 0x%04x/0x%04x",
+ funcName, dui->unpackFormat, dui->unpackType);
+ }
+
MOZ_ALWAYS_TRUE( webgl->gl->MakeCurrent() );
ScopedUnpackReset scopedReset(webgl);
webgl->gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, convertedAlignment);
error = DoTexOrSubImage(isSubImage, webgl->gl, target.get(), level, dui, xOffset,
yOffset, zOffset, mWidth, mHeight, mDepth,
convertedBuffer.get());
*out_glError = error;
--- a/dom/canvas/TexUnpackBlob.h
+++ b/dom/canvas/TexUnpackBlob.h
@@ -142,17 +142,17 @@ public:
GLint yOffset, GLint zOffset,
GLenum* const out_glError) 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_outOfMemory);
+ 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);
};
--- a/dom/canvas/WebGLTexelConversions.cpp
+++ b/dom/canvas/WebGLTexelConversions.cpp
@@ -344,18 +344,21 @@ public:
} // end anonymous namespace
bool
ConvertImage(size_t width, size_t height,
const void* srcBegin, size_t srcStride, gl::OriginPos srcOrigin,
WebGLTexelFormat srcFormat, bool srcPremultiplied,
void* dstBegin, size_t dstStride, gl::OriginPos dstOrigin,
- WebGLTexelFormat dstFormat, bool dstPremultiplied)
+ WebGLTexelFormat dstFormat, bool dstPremultiplied,
+ bool* const out_wasTrivial)
{
+ *out_wasTrivial = true;
+
if (srcFormat == WebGLTexelFormat::FormatNotSupportingAnyConversion ||
dstFormat == WebGLTexelFormat::FormatNotSupportingAnyConversion)
{
return false;
}
if (!width || !height)
return true;
@@ -405,16 +408,18 @@ ConvertImage(size_t width, size_t height
while (srcItr != srcEnd) {
memcpy(dstItr, srcItr, bytesPerRow);
srcItr += srcStride;
dstItr += dstItrStride;
}
return true;
}
+ *out_wasTrivial = false;
+
WebGLImageConverter converter(width, height, srcItr, dstItr, srcStride, dstItrStride);
converter.run(srcFormat, dstFormat, premultOp);
if (!converter.Success()) {
// the dst image may be left uninitialized, so we better not try to
// continue even in release builds. This should never happen anyway,
// and would be a bug in our code.
NS_RUNTIMEABORT("programming mistake in WebGL texture conversions");
--- a/dom/canvas/WebGLTexelConversions.h
+++ b/dom/canvas/WebGLTexelConversions.h
@@ -38,17 +38,18 @@
#include "mozilla/Casting.h"
namespace mozilla {
bool ConvertImage(size_t width, size_t height,
const void* srcBegin, size_t srcStride, gl::OriginPos srcOrigin,
WebGLTexelFormat srcFormat, bool srcPremultiplied,
void* dstBegin, size_t dstStride, gl::OriginPos dstOrigin,
- WebGLTexelFormat dstFormat, bool dstPremultiplied);
+ WebGLTexelFormat dstFormat, bool dstPremultiplied,
+ bool* out_wasTrivial);
//////////////////////////////////////////////////////////////////////////////////////////
// single precision float
// seeeeeeeemmmmmmmmmmmmmmmmmmmmmmm
// half precision float
// seeeeemmmmmmmmmm