123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* 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(surfaceSize,
- frameRect,
- aConfig.mFormat,
- /* aPaletteDepth */ 0,
- aConfig.mAnimParams);
- 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.mOutputSize,
- aConfig.mFrameRect,
- aConfig.mFormat,
- aConfig.mPaletteDepth,
- aConfig.mAnimParams);
- 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
|