tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SurfacePipe.cpp (5269B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "SurfacePipe.h"
      8 
      9 #include <algorithm>  // for min
     10 
     11 #include "Decoder.h"
     12 
     13 namespace mozilla {
     14 namespace image {
     15 
     16 using namespace gfx;
     17 
     18 using std::min;
     19 
     20 Maybe<SurfaceInvalidRect> AbstractSurfaceSink::TakeInvalidRect() {
     21  if (mInvalidRect.IsEmpty()) {
     22    return Nothing();
     23  }
     24 
     25  SurfaceInvalidRect invalidRect;
     26  invalidRect.mInputSpaceRect = invalidRect.mOutputSpaceRect = mInvalidRect;
     27 
     28  // Forget about the invalid rect we're returning.
     29  mInvalidRect = OrientedIntRect();
     30 
     31  return Some(invalidRect);
     32 }
     33 
     34 uint8_t* AbstractSurfaceSink::DoResetToFirstRow() {
     35  mRow = 0;
     36  return GetRowPointer();
     37 }
     38 
     39 uint8_t* SurfaceSink::DoAdvanceRowFromBuffer(const uint8_t* aInputRow) {
     40  CopyInputRow(aInputRow);
     41  return DoAdvanceRow();
     42 }
     43 
     44 uint8_t* SurfaceSink::DoAdvanceRow() {
     45  if (mRow >= uint32_t(InputSize().height)) {
     46    return nullptr;
     47  }
     48 
     49  // If we're vertically flipping the output, we need to flip the invalid rect.
     50  // Since we're dealing with an axis-aligned rect, only the y coordinate needs
     51  // to change.
     52  int32_t invalidY = mFlipVertically ? InputSize().height - (mRow + 1) : mRow;
     53  mInvalidRect.UnionRect(mInvalidRect,
     54                         OrientedIntRect(0, invalidY, InputSize().width, 1));
     55 
     56  mRow = min(uint32_t(InputSize().height), mRow + 1);
     57 
     58  return mRow < uint32_t(InputSize().height) ? GetRowPointer() : nullptr;
     59 }
     60 
     61 nsresult SurfaceSink::Configure(const SurfaceConfig& aConfig) {
     62  IntSize surfaceSize = aConfig.mOutputSize;
     63 
     64  // Allocate the frame.
     65  // XXX(seth): Once every Decoder subclass uses SurfacePipe, we probably want
     66  // to allocate the frame directly here and get rid of Decoder::AllocateFrame
     67  // altogether.
     68  nsresult rv = aConfig.mDecoder->AllocateFrame(surfaceSize, aConfig.mFormat,
     69                                                aConfig.mAnimParams);
     70  if (NS_FAILED(rv)) {
     71    return rv;
     72  }
     73 
     74  mImageData = aConfig.mDecoder->mImageData;
     75  mImageDataLength = aConfig.mDecoder->mImageDataLength;
     76  mFlipVertically = aConfig.mFlipVertically;
     77 
     78  MOZ_ASSERT(mImageData);
     79  MOZ_ASSERT(uint64_t(mImageDataLength) == uint64_t(surfaceSize.width) *
     80                                               uint64_t(surfaceSize.height) *
     81                                               sizeof(uint32_t));
     82 
     83  ConfigureFilter(surfaceSize, sizeof(uint32_t));
     84  return NS_OK;
     85 }
     86 
     87 uint8_t* SurfaceSink::GetRowPointer() const {
     88  // If we're flipping vertically, reverse the order in which we traverse the
     89  // rows.
     90  uint32_t row = mFlipVertically ? InputSize().height - (mRow + 1) : mRow;
     91 
     92  uint8_t* rowPtr = mImageData + row * InputSize().width * sizeof(uint32_t);
     93 
     94  MOZ_ASSERT(rowPtr >= mImageData);
     95  MOZ_ASSERT(rowPtr < mImageData + mImageDataLength);
     96  MOZ_ASSERT(rowPtr + InputSize().width * sizeof(uint32_t) <=
     97             mImageData + mImageDataLength);
     98 
     99  return rowPtr;
    100 }
    101 
    102 uint8_t* ReorientSurfaceSink::DoAdvanceRowFromBuffer(const uint8_t* aInputRow) {
    103  if (mRow >= uint32_t(InputSize().height)) {
    104    return nullptr;
    105  }
    106 
    107  IntRect dirty = mReorientFn(aInputRow, mRow, mImageData, mSurfaceSize,
    108                              mSurfaceSize.width * sizeof(uint32_t));
    109  auto orientedDirty = OrientedIntRect::FromUnknownRect(dirty);
    110  mInvalidRect.UnionRect(mInvalidRect, orientedDirty);
    111 
    112  mRow = min(uint32_t(InputSize().height), mRow + 1);
    113 
    114  return mRow < uint32_t(InputSize().height) ? GetRowPointer() : nullptr;
    115 }
    116 
    117 uint8_t* ReorientSurfaceSink::DoAdvanceRow() {
    118  return DoAdvanceRowFromBuffer(mBuffer.get());
    119 }
    120 
    121 nsresult ReorientSurfaceSink::Configure(const ReorientSurfaceConfig& aConfig) {
    122  mSurfaceSize = aConfig.mOutputSize.ToUnknownSize();
    123 
    124  // Allocate the frame.
    125  // XXX(seth): Once every Decoder subclass uses SurfacePipe, we probably want
    126  // to allocate the frame directly here and get rid of Decoder::AllocateFrame
    127  // altogether.
    128  nsresult rv =
    129      aConfig.mDecoder->AllocateFrame(mSurfaceSize, aConfig.mFormat, Nothing());
    130  if (NS_FAILED(rv)) {
    131    return rv;
    132  }
    133 
    134  // The filters above us need the unoriented size as the input.
    135  auto inputSize =
    136      aConfig.mOrientation.ToUnoriented(aConfig.mOutputSize).ToUnknownSize();
    137  mBuffer.reset(new (fallible) uint8_t[inputSize.width * sizeof(uint32_t)]);
    138  if (MOZ_UNLIKELY(!mBuffer)) {
    139    return NS_ERROR_OUT_OF_MEMORY;
    140  }
    141 
    142  memset(mBuffer.get(), 0xFF, inputSize.width * sizeof(uint32_t));
    143 
    144  mReorientFn = ReorientRow(aConfig.mOrientation);
    145  MOZ_ASSERT(mReorientFn);
    146 
    147  mImageData = aConfig.mDecoder->mImageData;
    148  mImageDataLength = aConfig.mDecoder->mImageDataLength;
    149 
    150  MOZ_ASSERT(mImageData);
    151  MOZ_ASSERT(uint64_t(mImageDataLength) == uint64_t(mSurfaceSize.width) *
    152                                               uint64_t(mSurfaceSize.height) *
    153                                               sizeof(uint32_t));
    154 
    155  ConfigureFilter(inputSize, sizeof(uint32_t));
    156  return NS_OK;
    157 }
    158 
    159 uint8_t* ReorientSurfaceSink::GetRowPointer() const { return mBuffer.get(); }
    160 
    161 }  // namespace image
    162 }  // namespace mozilla