Bug 1207830 (Part 1) - Make it possible to create an anonymous decoder that downscales. r=njn
☠☠ backed out by 6b521813510a ☠ ☠
authorSeth Fowler <mark.seth.fowler@gmail.com>
Thu, 26 May 2016 22:57:09 -0700
changeset 328323 1bc7102718a99bc960054cbad9f178df932234c8
parent 328322 d452f7cdc61e607a53c996798a14d93ab9d30378
child 328324 acbbb2038fdd02faf8228587b5d3d6cf7a9fb0d6
push idunknown
push userunknown
push dateunknown
reviewersnjn
bugs1207830
milestone49.0a1
Bug 1207830 (Part 1) - Make it possible to create an anonymous decoder that downscales. r=njn
image/DecoderFactory.cpp
image/DecoderFactory.h
image/ImageOps.cpp
image/test/gtest/Common.cpp
image/test/gtest/TestDecoders.cpp
image/test/gtest/TestMetadata.cpp
--- a/image/DecoderFactory.cpp
+++ b/image/DecoderFactory.cpp
@@ -199,16 +199,17 @@ DecoderFactory::CreateMetadataDecoder(De
   }
 
   return decoder.forget();
 }
 
 /* static */ already_AddRefed<Decoder>
 DecoderFactory::CreateAnonymousDecoder(DecoderType aType,
                                        SourceBuffer* aSourceBuffer,
+                                       const Maybe<IntSize>& aTargetSize,
                                        SurfaceFlags aSurfaceFlags)
 {
   if (aType == DecoderType::UNKNOWN) {
     return nullptr;
   }
 
   RefPtr<Decoder> decoder =
     GetDecoder(aType, /* aImage = */ nullptr, /* aIsRedecode = */ false);
@@ -227,16 +228,22 @@ DecoderFactory::CreateAnonymousDecoder(D
   // Decoder::GetCurrentFrame(). That means that anonymous decoders should
   // always be first-frame-only decoders, because nobody ever wants the *last*
   // frame.
   decoderFlags |= DecoderFlags::FIRST_FRAME_ONLY;
 
   decoder->SetDecoderFlags(decoderFlags);
   decoder->SetSurfaceFlags(aSurfaceFlags);
 
+  // Set a target size for downscale-during-decode if applicable.
+  if (aTargetSize) {
+    DebugOnly<nsresult> rv = decoder->SetTargetSize(*aTargetSize);
+    MOZ_ASSERT(NS_SUCCEEDED(rv), "Bad downscale-during-decode target size?");
+  }
+
   decoder->Init();
   if (NS_FAILED(decoder->GetDecoderError())) {
     return nullptr;
   }
 
   return decoder.forget();
 }
 
--- a/image/DecoderFactory.h
+++ b/image/DecoderFactory.h
@@ -115,22 +115,27 @@ public:
 
   /**
    * Creates and initializes an anonymous decoder (one which isn't associated
    * with an Image object). Only the first frame of the image will be decoded.
    *
    * @param aType Which type of decoder to create - JPEG, PNG, etc.
    * @param aSourceBuffer The SourceBuffer which the decoder will read its data
    *                      from.
+   * @param aTargetSize If not Nothing(), the target size which the image should
+   *                    be scaled to during decoding. It's an error to specify
+   *                    a target size for a decoder type which doesn't support
+   *                    downscale-during-decode.
    * @param aSurfaceFlags Flags specifying the type of output this decoder
    *                      should produce.
    */
   static already_AddRefed<Decoder>
   CreateAnonymousDecoder(DecoderType aType,
                          SourceBuffer* aSourceBuffer,
+                         const Maybe<gfx::IntSize>& aTargetSize,
                          SurfaceFlags aSurfaceFlags);
 
   /**
    * Creates and initializes an anonymous metadata decoder (one which isn't
    * associated with an Image object). This decoder will only decode the image's
    * header, extracting metadata like the size of the image. No actual image
    * data will be decoded and no surfaces will be allocated.
    *
--- a/image/ImageOps.cpp
+++ b/image/ImageOps.cpp
@@ -115,16 +115,17 @@ ImageOps::DecodeToSurface(nsIInputStream
   sourceBuffer->Complete(NS_OK);
 
   // Create a decoder.
   DecoderType decoderType =
     DecoderFactory::GetDecoderType(PromiseFlatCString(aMimeType).get());
   RefPtr<Decoder> decoder =
     DecoderFactory::CreateAnonymousDecoder(decoderType,
                                            sourceBuffer,
+                                           Nothing(),
                                            ToSurfaceFlags(aFlags));
   if (!decoder) {
     return nullptr;
   }
 
   // Run the decoder synchronously.
   decoder->Decode();
   if (!decoder->GetDecodeDone() || decoder->HasError()) {
--- a/image/test/gtest/Common.cpp
+++ b/image/test/gtest/Common.cpp
@@ -156,17 +156,17 @@ RectIsSolidColor(SourceSurface* aSurface
 
 already_AddRefed<Decoder>
 CreateTrivialDecoder()
 {
   gfxPrefs::GetSingleton();
   DecoderType decoderType = DecoderFactory::GetDecoderType("image/gif");
   RefPtr<SourceBuffer> sourceBuffer = new SourceBuffer();
   RefPtr<Decoder> decoder =
-    DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer,
+    DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer, Nothing(),
                                            DefaultSurfaceFlags());
   return decoder.forget();
 }
 
 void AssertCorrectPipelineFinalState(SurfaceFilter* aFilter,
                                      const gfx::IntRect& aInputSpaceRect,
                                      const gfx::IntRect& aOutputSpaceRect)
 {
--- a/image/test/gtest/TestDecoders.cpp
+++ b/image/test/gtest/TestDecoders.cpp
@@ -99,17 +99,17 @@ CheckDecoderSingleChunk(const ImageTestC
   rv = sourceBuffer->AppendFromInputStream(inputStream, length);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
   sourceBuffer->Complete(NS_OK);
 
   // Create a decoder.
   DecoderType decoderType =
     DecoderFactory::GetDecoderType(aTestCase.mMimeType);
   RefPtr<Decoder> decoder =
-    DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer,
+    DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer, Nothing(),
                                            DefaultSurfaceFlags());
   ASSERT_TRUE(decoder != nullptr);
 
   // Run the full decoder synchronously.
   decoder->Decode();
   
   CheckDecoderResults(aTestCase, decoder);
 }
@@ -136,17 +136,17 @@ CheckDecoderMultiChunk(const ImageTestCa
   ASSERT_TRUE(NS_SUCCEEDED(rv));
 
   // Create a SourceBuffer and a decoder.
   RefPtr<SourceBuffer> sourceBuffer = new SourceBuffer();
   sourceBuffer->ExpectLength(length);
   DecoderType decoderType =
     DecoderFactory::GetDecoderType(aTestCase.mMimeType);
   RefPtr<Decoder> decoder =
-    DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer,
+    DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer, Nothing(),
                                            DefaultSurfaceFlags());
   ASSERT_TRUE(decoder != nullptr);
 
   // Decode synchronously, using a |NoResume| IResumable so the Decoder doesn't
   // attempt to schedule itself on a nonexistent DecodePool when we write more
   // data into the SourceBuffer.
   RefPtr<NoResume> noResume = new NoResume();
   for (uint64_t read = 0; read < length ; ++read) {
--- a/image/test/gtest/TestMetadata.cpp
+++ b/image/test/gtest/TestMetadata.cpp
@@ -105,17 +105,17 @@ CheckMetadata(const ImageTestCase& aTest
                           : bool(aTestCase.mFlags & TEST_CASE_IS_TRANSPARENT);
   EXPECT_EQ(expectTransparency, bool(metadataProgress & FLAG_HAS_TRANSPARENCY));
 
   EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_ANIMATED),
             bool(metadataProgress & FLAG_IS_ANIMATED));
 
   // Create a full decoder, so we can compare the result.
   decoder =
-    DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer,
+    DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer, Nothing(),
                                            DefaultSurfaceFlags());
   ASSERT_TRUE(decoder != nullptr);
 
   if (aBMPWithinICO == BMPWithinICO::YES) {
     static_cast<nsBMPDecoder*>(decoder.get())->SetIsWithinICO();
   }
 
   // Run the full decoder synchronously.