Bug 1551088 - Part 5. Expose SurfaceFilter input row directly to avoid copy if possible. r=tnikkel

Some filters can do the copy of the given data into the working buffer
as part of the filter operation. For those that cannot, we will just
copy the data first, and then advance the row.

Differential Revision: https://phabricator.services.mozilla.com/D46448

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Andrew Osmond 2019-09-24 20:42:45 +00:00
Родитель 94b66bc792
Коммит 1c40442ec4
4 изменённых файлов: 96 добавлений и 6 удалений

Просмотреть файл

@ -78,6 +78,10 @@ class DownscalingFilter final : public SurfaceFilter {
MOZ_CRASH();
return nullptr;
}
uint8_t* DoAdvanceRowFromBuffer(const uint8_t* aInputRow) override {
MOZ_CRASH();
return nullptr;
}
uint8_t* DoAdvanceRow() override {
MOZ_CRASH();
return nullptr;
@ -206,7 +210,7 @@ class DownscalingFilter final : public SurfaceFilter {
return GetRowPointer();
}
uint8_t* DoAdvanceRow() override {
uint8_t* DoAdvanceRowFromBuffer(const uint8_t* aInputRow) override {
if (mInputRow >= mInputSize.height) {
NS_WARNING("Advancing DownscalingFilter past the end of the input");
return nullptr;
@ -226,7 +230,7 @@ class DownscalingFilter final : public SurfaceFilter {
if (mInputRow == inputRowToRead) {
MOZ_RELEASE_ASSERT(mRowsInWindow < mWindowCapacity,
"Need more rows than capacity!");
mXFilter.ConvolveHorizontally(mRowBuffer.get(), mWindow[mRowsInWindow++],
mXFilter.ConvolveHorizontally(aInputRow, mWindow[mRowsInWindow++],
mHasAlpha);
}
@ -249,6 +253,10 @@ class DownscalingFilter final : public SurfaceFilter {
return mInputRow < mInputSize.height ? GetRowPointer() : nullptr;
}
uint8_t* DoAdvanceRow() override {
return DoAdvanceRowFromBuffer(mRowBuffer.get());
}
private:
uint8_t* GetRowPointer() const { return mRowBuffer.get(); }

Просмотреть файл

@ -80,12 +80,16 @@ class ColorManagementFilter final : public SurfaceFilter {
protected:
uint8_t* DoResetToFirstRow() override { return mNext.ResetToFirstRow(); }
uint8_t* DoAdvanceRow() override {
uint8_t* rowPtr = mNext.CurrentRowPointer();
qcms_transform_data(mTransform, rowPtr, rowPtr, mNext.InputSize().width);
uint8_t* DoAdvanceRowFromBuffer(const uint8_t* aInputRow) override {
qcms_transform_data(mTransform, aInputRow, mNext.CurrentRowPointer(),
mNext.InputSize().width);
return mNext.AdvanceRow();
}
uint8_t* DoAdvanceRow() override {
return DoAdvanceRowFromBuffer(mNext.CurrentRowPointer());
}
Next mNext; /// The next SurfaceFilter in the chain.
qcms_transform* mTransform;
@ -182,6 +186,11 @@ class DeinterlacingFilter final : public SurfaceFilter {
return GetRowPointer(mOutputRow);
}
uint8_t* DoAdvanceRowFromBuffer(const uint8_t* aInputRow) override {
CopyInputRow(aInputRow);
return DoAdvanceRow();
}
uint8_t* DoAdvanceRow() override {
if (mPass >= 4) {
return nullptr; // We already finished all passes.
@ -638,6 +647,11 @@ class BlendAnimationFilter final : public SurfaceFilter {
return nullptr; // We're done.
}
uint8_t* DoAdvanceRowFromBuffer(const uint8_t* aInputRow) override {
CopyInputRow(aInputRow);
return DoAdvanceRow();
}
uint8_t* DoAdvanceRow() override {
uint8_t* rowPtr = nullptr;
@ -912,6 +926,11 @@ class RemoveFrameRectFilter final : public SurfaceFilter {
return nullptr; // We're done.
}
uint8_t* DoAdvanceRowFromBuffer(const uint8_t* aInputRow) override {
CopyInputRow(aInputRow);
return DoAdvanceRow();
}
uint8_t* DoAdvanceRow() override {
uint8_t* rowPtr = nullptr;
@ -1097,6 +1116,11 @@ class ADAM7InterpolatingFilter final : public SurfaceFilter {
return mCurrentRow.get();
}
uint8_t* DoAdvanceRowFromBuffer(const uint8_t* aInputRow) override {
CopyInputRow(aInputRow);
return DoAdvanceRow();
}
uint8_t* DoAdvanceRow() override {
MOZ_ASSERT(0 < mPass && mPass <= 7, "Invalid pass");

Просмотреть файл

@ -36,6 +36,11 @@ uint8_t* AbstractSurfaceSink::DoResetToFirstRow() {
return GetRowPointer();
}
uint8_t* AbstractSurfaceSink::DoAdvanceRowFromBuffer(const uint8_t* aInputRow) {
CopyInputRow(aInputRow);
return DoAdvanceRow();
}
uint8_t* AbstractSurfaceSink::DoAdvanceRow() {
if (mRow >= uint32_t(InputSize().height)) {
return nullptr;

Просмотреть файл

@ -127,6 +127,19 @@ class SurfaceFilter {
return mRowPointer;
}
/**
* Called by WriteBuffer() to advance this filter to the next row, if the
* supplied row is a full row.
*
* @return a pointer to the buffer for the next row, or nullptr to indicate
* that we've finished the entire surface.
*/
uint8_t* AdvanceRow(const uint8_t* aInputRow) {
mCol = 0;
mRowPointer = DoAdvanceRowFromBuffer(aInputRow);
return mRowPointer;
}
/// @return a pointer to the buffer for the current row.
uint8_t* CurrentRowPointer() const { return mRowPointer; }
@ -269,7 +282,22 @@ class SurfaceFilter {
*/
template <typename PixelType>
WriteState WriteBuffer(const PixelType* aSource) {
return WriteBuffer(aSource, 0, mInputSize.width);
MOZ_ASSERT(mPixelSize == 1 || mPixelSize == 4);
MOZ_ASSERT_IF(mPixelSize == 1, sizeof(PixelType) == sizeof(uint8_t));
MOZ_ASSERT_IF(mPixelSize == 4, sizeof(PixelType) == sizeof(uint32_t));
if (IsSurfaceFinished()) {
return WriteState::FINISHED; // Already done.
}
if (MOZ_UNLIKELY(!aSource)) {
NS_WARNING("Passed a null pointer to WriteBuffer");
return WriteState::FAILURE;
}
AdvanceRow(reinterpret_cast<const uint8_t*>(aSource));
return IsSurfaceFinished() ? WriteState::FINISHED
: WriteState::NEED_MORE_DATA;
}
/**
@ -440,6 +468,16 @@ class SurfaceFilter {
*/
virtual uint8_t* DoResetToFirstRow() = 0;
/**
* Called by AdvanceRow() to actually advance this filter to the next row.
*
* @param aInputRow The input row supplied by the decoder.
*
* @return a pointer to the buffer for the next row, or nullptr to indicate
* that we've finished the entire surface.
*/
virtual uint8_t* DoAdvanceRowFromBuffer(const uint8_t* aInputRow) = 0;
/**
* Called by AdvanceRow() to actually advance this filter to the next row.
*
@ -470,6 +508,20 @@ class SurfaceFilter {
ResetToFirstRow();
}
/**
* Called by subclasses' DoAdvanceRowFromBuffer() methods to copy a decoder
* supplied row buffer into its internal row pointer. Ideally filters at the
* top of the filter pipeline are able to consume the decoder row buffer
* directly without the extra copy prior to performing its transformation.
*
* @param aInputRow The input row supplied by the decoder.
*/
void CopyInputRow(const uint8_t* aInputRow) {
MOZ_ASSERT(aInputRow);
MOZ_ASSERT(mCol == 0);
memcpy(mRowPointer, aInputRow, mPixelSize * mInputSize.width);
}
private:
/**
* An internal method used to implement WritePixelBlocks. This method writes
@ -719,6 +771,7 @@ class AbstractSurfaceSink : public SurfaceFilter {
protected:
uint8_t* DoResetToFirstRow() final;
uint8_t* DoAdvanceRowFromBuffer(const uint8_t* aInputRow) final;
uint8_t* DoAdvanceRow() final;
virtual uint8_t* GetRowPointer() const = 0;