Bug 1276093 - r?jrmuizel - Warn on slow CPU format conversions. draft
authorJeff Gilbert <jdashg@gmail.com>
Thu, 26 May 2016 16:59:06 -0700
changeset 371863 dfdca88090ccd49f2da07256150d47117de258c8
parent 370842 d6d4e8417d2fd71fdf47c319b7a217f6ace9d5a5
child 371864 30692eeb21e68e06dde51c4f73e1ee383a71e5d7
push id19372
push userjgilbert@mozilla.com
push dateFri, 27 May 2016 00:06:00 +0000
reviewersjrmuizel
bugs1276093
milestone49.0a1
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
dom/canvas/TexUnpackBlob.cpp
dom/canvas/TexUnpackBlob.h
dom/canvas/WebGLTexelConversions.cpp
dom/canvas/WebGLTexelConversions.h
--- 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