summaryrefslogtreecommitdiffstats
path: root/image/SurfacePipe.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'image/SurfacePipe.cpp')
-rw-r--r--image/SurfacePipe.cpp199
1 files changed, 199 insertions, 0 deletions
diff --git a/image/SurfacePipe.cpp b/image/SurfacePipe.cpp
new file mode 100644
index 000000000..5c306144a
--- /dev/null
+++ b/image/SurfacePipe.cpp
@@ -0,0 +1,199 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 "SurfacePipe.h"
+
+#include <utility>
+
+#include "mozilla/ClearOnShutdown.h"
+#include "mozilla/DebugOnly.h"
+#include "Decoder.h"
+
+namespace mozilla {
+namespace image {
+
+using namespace gfx;
+
+using std::min;
+
+/* static */ UniquePtr<NullSurfaceSink> NullSurfaceSink::sSingleton;
+
+/* static */ NullSurfaceSink*
+NullSurfaceSink::Singleton()
+{
+ if (!sSingleton) {
+ MOZ_ASSERT(NS_IsMainThread());
+ sSingleton = MakeUnique<NullSurfaceSink>();
+ ClearOnShutdown(&sSingleton);
+
+ DebugOnly<nsresult> rv = sSingleton->Configure(NullSurfaceConfig { });
+ MOZ_ASSERT(NS_SUCCEEDED(rv), "Couldn't configure a NullSurfaceSink?");
+ }
+
+ return sSingleton.get();
+}
+
+nsresult
+NullSurfaceSink::Configure(const NullSurfaceConfig& aConfig)
+{
+ // Note that the choice of uint32_t as the pixel size here is more or less
+ // arbitrary, since you cannot write to a NullSurfaceSink anyway, but uint32_t
+ // is a natural choice since most SurfacePipes will be for BGRA/BGRX surfaces.
+ ConfigureFilter(IntSize(), sizeof(uint32_t));
+ return NS_OK;
+}
+
+Maybe<SurfaceInvalidRect>
+AbstractSurfaceSink::TakeInvalidRect()
+{
+ if (mInvalidRect.IsEmpty()) {
+ return Nothing();
+ }
+
+ SurfaceInvalidRect invalidRect;
+ invalidRect.mInputSpaceRect = invalidRect.mOutputSpaceRect = mInvalidRect;
+
+ // Forget about the invalid rect we're returning.
+ mInvalidRect = IntRect();
+
+ return Some(invalidRect);
+}
+
+uint8_t*
+AbstractSurfaceSink::DoResetToFirstRow()
+{
+ mRow = 0;
+ return GetRowPointer();
+}
+
+uint8_t*
+AbstractSurfaceSink::DoAdvanceRow()
+{
+ if (mRow >= uint32_t(InputSize().height)) {
+ return nullptr;
+ }
+
+ // If we're vertically flipping the output, we need to flip the invalid rect. Since we're
+ // dealing with an axis-aligned rect, only the y coordinate needs to change.
+ int32_t invalidY = mFlipVertically
+ ? InputSize().height - (mRow + 1)
+ : mRow;
+ mInvalidRect.UnionRect(mInvalidRect,
+ IntRect(0, invalidY, InputSize().width, 1));
+
+ mRow = min(uint32_t(InputSize().height), mRow + 1);
+
+ return mRow < uint32_t(InputSize().height) ? GetRowPointer()
+ : nullptr;
+}
+
+nsresult
+SurfaceSink::Configure(const SurfaceConfig& aConfig)
+{
+ // For non-paletted surfaces, the surface size is just the output size.
+ IntSize surfaceSize = aConfig.mOutputSize;
+
+ // Non-paletted surfaces should not have frame rects, so we just pass
+ // AllocateFrame() a frame rect which covers the entire surface.
+ IntRect frameRect(0, 0, surfaceSize.width, surfaceSize.height);
+
+ // Allocate the frame.
+ // XXX(seth): Once every Decoder subclass uses SurfacePipe, we probably want
+ // to allocate the frame directly here and get rid of Decoder::AllocateFrame
+ // altogether.
+ nsresult rv = aConfig.mDecoder->AllocateFrame(aConfig.mFrameNum,
+ surfaceSize,
+ frameRect,
+ aConfig.mFormat);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ mImageData = aConfig.mDecoder->mImageData;
+ mImageDataLength = aConfig.mDecoder->mImageDataLength;
+ mFlipVertically = aConfig.mFlipVertically;
+
+ MOZ_ASSERT(mImageData);
+ MOZ_ASSERT(mImageDataLength ==
+ uint32_t(surfaceSize.width * surfaceSize.height * sizeof(uint32_t)));
+
+ ConfigureFilter(surfaceSize, sizeof(uint32_t));
+ return NS_OK;
+}
+
+uint8_t*
+SurfaceSink::GetRowPointer() const
+{
+ // If we're flipping vertically, reverse the order in which we traverse the
+ // rows.
+ uint32_t row = mFlipVertically
+ ? InputSize().height - (mRow + 1)
+ : mRow;
+
+ uint8_t* rowPtr = mImageData + row * InputSize().width * sizeof(uint32_t);
+
+ MOZ_ASSERT(rowPtr >= mImageData);
+ MOZ_ASSERT(rowPtr < mImageData + mImageDataLength);
+ MOZ_ASSERT(rowPtr + InputSize().width * sizeof(uint32_t) <=
+ mImageData + mImageDataLength);
+
+ return rowPtr;
+}
+
+
+nsresult
+PalettedSurfaceSink::Configure(const PalettedSurfaceConfig& aConfig)
+{
+ // For paletted surfaces, the surface size is the size of the frame rect.
+ IntSize surfaceSize = aConfig.mFrameRect.Size();
+
+ // Allocate the frame.
+ // XXX(seth): Once every Decoder subclass uses SurfacePipe, we probably want
+ // to allocate the frame directly here and get rid of Decoder::AllocateFrame
+ // altogether.
+ nsresult rv = aConfig.mDecoder->AllocateFrame(aConfig.mFrameNum,
+ aConfig.mOutputSize,
+ aConfig.mFrameRect,
+ aConfig.mFormat,
+ aConfig.mPaletteDepth);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ mImageData = aConfig.mDecoder->mImageData;
+ mImageDataLength = aConfig.mDecoder->mImageDataLength;
+ mFlipVertically = aConfig.mFlipVertically;
+ mFrameRect = aConfig.mFrameRect;
+
+ MOZ_ASSERT(mImageData);
+ MOZ_ASSERT(mImageDataLength ==
+ uint32_t(mFrameRect.width * mFrameRect.height * sizeof(uint8_t)));
+
+ ConfigureFilter(surfaceSize, sizeof(uint8_t));
+ return NS_OK;
+}
+
+uint8_t*
+PalettedSurfaceSink::GetRowPointer() const
+{
+ // If we're flipping vertically, reverse the order in which we traverse the
+ // rows.
+ uint32_t row = mFlipVertically
+ ? InputSize().height - (mRow + 1)
+ : mRow;
+
+ uint8_t* rowPtr = mImageData + row * InputSize().width * sizeof(uint8_t);
+
+ MOZ_ASSERT(rowPtr >= mImageData);
+ MOZ_ASSERT(rowPtr < mImageData + mImageDataLength);
+ MOZ_ASSERT(rowPtr + InputSize().width * sizeof(uint8_t) <=
+ mImageData + mImageDataLength);
+
+ return rowPtr;
+}
+
+} // namespace image
+} // namespace mozilla