Bug 1551088 - Part 7. Add gtests for SwizzleFilter. r=tnikkel

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Andrew Osmond 2019-09-20 18:53:56 +00:00
Родитель 7f20ed4927
Коммит cf7d9c7ae1
4 изменённых файлов: 142 добавлений и 181 удалений

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

@ -167,11 +167,6 @@ bool IsSolidColor(SourceSurface* aSurface, BGRAColor aColor,
aColor, aFuzz);
}
bool IsSolidPalettedColor(Decoder* aDecoder, uint8_t aColor) {
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
return PalettedRectIsSolidColor(aDecoder, currentFrame->GetRect(), aColor);
}
bool RowsAreSolidColor(SourceSurface* aSurface, int32_t aStartRow,
int32_t aRowCount, BGRAColor aColor,
uint8_t aFuzz /* = 0 */) {
@ -180,15 +175,6 @@ bool RowsAreSolidColor(SourceSurface* aSurface, int32_t aStartRow,
aSurface, IntRect(0, aStartRow, size.width, aRowCount), aColor, aFuzz);
}
bool PalettedRowsAreSolidColor(Decoder* aDecoder, int32_t aStartRow,
int32_t aRowCount, uint8_t aColor) {
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
IntRect frameRect = currentFrame->GetRect();
IntRect solidColorRect(frameRect.X(), aStartRow, frameRect.Width(),
aRowCount);
return PalettedRectIsSolidColor(aDecoder, solidColorRect, aColor);
}
bool RectIsSolidColor(SourceSurface* aSurface, const IntRect& aRect,
BGRAColor aColor, uint8_t aFuzz /* = 0 */) {
IntSize surfaceSize = aSurface->GetSize();
@ -228,42 +214,6 @@ bool RectIsSolidColor(SourceSurface* aSurface, const IntRect& aRect,
return true;
}
bool PalettedRectIsSolidColor(Decoder* aDecoder, const IntRect& aRect,
uint8_t aColor) {
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
uint8_t* imageData;
uint32_t imageLength;
currentFrame->GetImageData(&imageData, &imageLength);
ASSERT_TRUE_OR_RETURN(imageData, false);
// Clamp to the frame rect. If any pixels outside the frame rect are included,
// we immediately fail, because such pixels don't have any "color" in the
// sense this function measures - they're transparent, and that doesn't
// necessarily correspond to any color palette index at all.
IntRect frameRect = currentFrame->GetRect();
ASSERT_EQ_OR_RETURN(imageLength, uint32_t(frameRect.Area()), false);
IntRect rect = aRect.Intersect(frameRect);
ASSERT_EQ_OR_RETURN(rect.Area(), aRect.Area(), false);
// Translate |rect| by |frameRect.TopLeft()| to reflect the fact that the
// frame rect's offset doesn't actually mean anything in terms of the
// in-memory representation of the surface. The image data starts at the upper
// left corner of the frame rect, in other words.
rect -= frameRect.TopLeft();
// Walk through the image data and make sure that the entire rect has the
// palette index |aColor|.
int32_t rowLength = frameRect.Width();
for (int32_t row = rect.Y(); row < rect.YMost(); ++row) {
for (int32_t col = rect.X(); col < rect.XMost(); ++col) {
int32_t i = row * rowLength + col;
ASSERT_EQ_OR_RETURN(aColor, imageData[i], false);
}
}
return true;
}
bool RowHasPixels(SourceSurface* aSurface, int32_t aRow,
const vector<BGRAColor>& aPixels) {
ASSERT_GE_OR_RETURN(aRow, 0, false);
@ -372,93 +322,20 @@ void CheckGeneratedSurface(SourceSurface* aSurface, const IntRect& aRect,
aOuterColor, aFuzz));
}
void CheckGeneratedPalettedImage(Decoder* aDecoder, const IntRect& aRect) {
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
IntSize imageSize = currentFrame->GetSize();
// This diagram shows how the surface is divided into regions that the code
// below tests for the correct content. The output rect is the bounds of the
// region labeled 'C'.
//
// +---------------------------+
// | A |
// +---------+--------+--------+
// | B | C | D |
// +---------+--------+--------+
// | E |
// +---------------------------+
// Check that the output rect itself is all 255's. (Region 'C'.)
EXPECT_TRUE(PalettedRectIsSolidColor(aDecoder, aRect, 255));
// Check that the area above the output rect is all 0's. (Region 'A'.)
EXPECT_TRUE(PalettedRectIsSolidColor(
aDecoder, IntRect(0, 0, imageSize.width, aRect.Y()), 0));
// Check that the area to the left of the output rect is all 0's. (Region
// 'B'.)
EXPECT_TRUE(PalettedRectIsSolidColor(
aDecoder, IntRect(0, aRect.Y(), aRect.X(), aRect.YMost()), 0));
// Check that the area to the right of the output rect is all 0's. (Region
// 'D'.)
const int32_t widthOnRight = imageSize.width - aRect.XMost();
EXPECT_TRUE(PalettedRectIsSolidColor(
aDecoder, IntRect(aRect.XMost(), aRect.Y(), widthOnRight, aRect.YMost()),
0));
// Check that the area below the output rect is transparent. (Region 'E'.)
const int32_t heightBelow = imageSize.height - aRect.YMost();
EXPECT_TRUE(PalettedRectIsSolidColor(
aDecoder, IntRect(0, aRect.YMost(), imageSize.width, heightBelow), 0));
}
void CheckWritePixels(Decoder* aDecoder, SurfaceFilter* aFilter,
const Maybe<IntRect>& aOutputRect /* = Nothing() */,
const Maybe<IntRect>& aInputRect /* = Nothing() */,
const Maybe<IntRect>& aInputWriteRect /* = Nothing() */,
const Maybe<IntRect>& aOutputWriteRect /* = Nothing() */,
uint8_t aFuzz /* = 0 */) {
IntRect outputRect = aOutputRect.valueOr(IntRect(0, 0, 100, 100));
IntRect inputRect = aInputRect.valueOr(IntRect(0, 0, 100, 100));
IntRect inputWriteRect = aInputWriteRect.valueOr(inputRect);
IntRect outputWriteRect = aOutputWriteRect.valueOr(outputRect);
// Fill the image.
int32_t count = 0;
auto result = aFilter->WritePixels<uint32_t>([&] {
++count;
return AsVariant(BGRAColor::Green().AsPixel());
});
EXPECT_EQ(WriteState::FINISHED, result);
EXPECT_EQ(inputWriteRect.Width() * inputWriteRect.Height(), count);
AssertCorrectPipelineFinalState(aFilter, inputRect, outputRect);
// Attempt to write more data and make sure nothing changes.
const int32_t oldCount = count;
result = aFilter->WritePixels<uint32_t>([&] {
++count;
return AsVariant(BGRAColor::Green().AsPixel());
});
EXPECT_EQ(oldCount, count);
EXPECT_EQ(WriteState::FINISHED, result);
EXPECT_TRUE(aFilter->IsSurfaceFinished());
Maybe<SurfaceInvalidRect> invalidRect = aFilter->TakeInvalidRect();
EXPECT_TRUE(invalidRect.isNothing());
// Attempt to advance to the next row and make sure nothing changes.
aFilter->AdvanceRow();
EXPECT_TRUE(aFilter->IsSurfaceFinished());
invalidRect = aFilter->TakeInvalidRect();
EXPECT_TRUE(invalidRect.isNothing());
// Check that the generated image is correct.
CheckGeneratedImage(aDecoder, outputWriteRect, aFuzz);
CheckTransformedWritePixels(aDecoder, aFilter, BGRAColor::Green(),
BGRAColor::Green(), aOutputRect, aInputRect,
aInputWriteRect, aOutputWriteRect, aFuzz);
}
void CheckPalettedWritePixels(
Decoder* aDecoder, SurfaceFilter* aFilter,
void CheckTransformedWritePixels(
Decoder* aDecoder, SurfaceFilter* aFilter, const BGRAColor& aInputColor,
const BGRAColor& aOutputColor,
const Maybe<IntRect>& aOutputRect /* = Nothing() */,
const Maybe<IntRect>& aInputRect /* = Nothing() */,
const Maybe<IntRect>& aInputWriteRect /* = Nothing() */,
@ -471,9 +348,9 @@ void CheckPalettedWritePixels(
// Fill the image.
int32_t count = 0;
auto result = aFilter->WritePixels<uint8_t>([&] {
auto result = aFilter->WritePixels<uint32_t>([&] {
++count;
return AsVariant(uint8_t(255));
return AsVariant(aInputColor.AsPixel());
});
EXPECT_EQ(WriteState::FINISHED, result);
EXPECT_EQ(inputWriteRect.Width() * inputWriteRect.Height(), count);
@ -482,9 +359,9 @@ void CheckPalettedWritePixels(
// Attempt to write more data and make sure nothing changes.
const int32_t oldCount = count;
result = aFilter->WritePixels<uint8_t>([&] {
result = aFilter->WritePixels<uint32_t>([&] {
++count;
return AsVariant(uint8_t(255));
return AsVariant(aInputColor.AsPixel());
});
EXPECT_EQ(oldCount, count);
EXPECT_EQ(WriteState::FINISHED, result);
@ -500,15 +377,9 @@ void CheckPalettedWritePixels(
// Check that the generated image is correct.
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
uint8_t* imageData;
uint32_t imageLength;
currentFrame->GetImageData(&imageData, &imageLength);
ASSERT_TRUE(imageData != nullptr);
ASSERT_EQ(outputWriteRect.Width() * outputWriteRect.Height(),
int32_t(imageLength));
for (uint32_t i = 0; i < imageLength; ++i) {
ASSERT_EQ(uint8_t(255), imageData[i]);
}
RefPtr<SourceSurface> surface = currentFrame->GetSourceSurface();
CheckGeneratedSurface(surface, outputWriteRect, aOutputColor,
BGRAColor::Transparent(), aFuzz);
}
///////////////////////////////////////////////////////////////////////////////

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

@ -158,12 +158,6 @@ already_AddRefed<nsIInputStream> LoadFile(const char* aRelativePath);
bool IsSolidColor(gfx::SourceSurface* aSurface, BGRAColor aColor,
uint8_t aFuzz = 0);
/**
* @returns true if every pixel of @aDecoder's surface has the palette index
* specified by @aColor.
*/
bool IsSolidPalettedColor(Decoder* aDecoder, uint8_t aColor);
/**
* @returns true if every pixel in the range of rows specified by @aStartRow and
* @aRowCount of @aSurface is @aColor.
@ -175,13 +169,6 @@ bool IsSolidPalettedColor(Decoder* aDecoder, uint8_t aColor);
bool RowsAreSolidColor(gfx::SourceSurface* aSurface, int32_t aStartRow,
int32_t aRowCount, BGRAColor aColor, uint8_t aFuzz = 0);
/**
* @returns true if every pixel in the range of rows specified by @aStartRow and
* @aRowCount of @aDecoder's surface has the palette index specified by @aColor.
*/
bool PalettedRowsAreSolidColor(Decoder* aDecoder, int32_t aStartRow,
int32_t aRowCount, uint8_t aColor);
/**
* @returns true if every pixel in the rect specified by @aRect is @aColor.
*
@ -192,13 +179,6 @@ bool PalettedRowsAreSolidColor(Decoder* aDecoder, int32_t aStartRow,
bool RectIsSolidColor(gfx::SourceSurface* aSurface, const gfx::IntRect& aRect,
BGRAColor aColor, uint8_t aFuzz = 0);
/**
* @returns true if every pixel in the rect specified by @aRect has the palette
* index specified by @aColor.
*/
bool PalettedRectIsSolidColor(Decoder* aDecoder, const gfx::IntRect& aRect,
uint8_t aColor);
/**
* @returns true if the pixels in @aRow of @aSurface match the pixels given in
* @aPixels.
@ -244,9 +224,9 @@ class CountResumes : public IResumable {
* that requires a decoder to initialize or to allocate surfaces but doesn't
* actually need the decoder to do any decoding.
*
* XXX(seth): We only need this because SurfaceSink and PalettedSurfaceSink
* defer to the decoder for surface allocation. Once all decoders use
* SurfacePipe we won't need to do that anymore and we can remove this function.
* XXX(seth): We only need this because SurfaceSink defer to the decoder for
* surface allocation. Once all decoders use SurfacePipe we won't need to do
* that anymore and we can remove this function.
*/
already_AddRefed<Decoder> CreateTrivialDecoder();
@ -349,19 +329,6 @@ void CheckGeneratedSurface(gfx::SourceSurface* aSurface,
const BGRAColor& aInnerColor,
const BGRAColor& aOuterColor, uint8_t aFuzz = 0);
/**
* Checks a generated paletted image for correctness. Reports any unexpected
* deviation from the expected image as GTest failures.
*
* @param aDecoder The decoder which contains the image. The decoder's current
* frame will be checked.
* @param aRect The region in the space of the output surface that the filter
* pipeline will actually write to. It's expected that pixels in
* this region have a palette index of 255, while pixels outside
* this region have a palette index of 0.
*/
void CheckGeneratedPalettedImage(Decoder* aDecoder, const gfx::IntRect& aRect);
/**
* Tests the result of calling WritePixels() using the provided SurfaceFilter
* pipeline. The pipeline must be a normal (i.e., non-paletted) pipeline.
@ -399,11 +366,13 @@ void CheckWritePixels(Decoder* aDecoder, SurfaceFilter* aFilter,
/**
* Tests the result of calling WritePixels() using the provided SurfaceFilter
* pipeline. The pipeline must be a paletted pipeline.
* pipeline. Allows for control over the input color to write, and the expected
* output color.
* @see CheckWritePixels() for documentation of the arguments.
*/
void CheckPalettedWritePixels(
Decoder* aDecoder, SurfaceFilter* aFilter,
void CheckTransformedWritePixels(
Decoder* aDecoder, SurfaceFilter* aFilter, const BGRAColor& aInputColor,
const BGRAColor& aOutputColor,
const Maybe<gfx::IntRect>& aOutputRect = Nothing(),
const Maybe<gfx::IntRect>& aInputRect = Nothing(),
const Maybe<gfx::IntRect>& aInputWriteRect = Nothing(),

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

@ -0,0 +1,120 @@
/* -*- 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 "gtest/gtest.h"
#include "mozilla/gfx/2D.h"
#include "Common.h"
#include "Decoder.h"
#include "DecoderFactory.h"
#include "SurfaceFilters.h"
#include "SurfacePipe.h"
using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::image;
template <typename Func>
void WithSwizzleFilter(const IntSize& aSize, SurfaceFormat aInputFormat,
SurfaceFormat aOutputFormat, bool aPremultiplyAlpha,
Func aFunc) {
RefPtr<Decoder> decoder = CreateTrivialDecoder();
ASSERT_TRUE(decoder != nullptr);
WithFilterPipeline(
decoder, std::forward<Func>(aFunc),
SwizzleConfig{aInputFormat, aOutputFormat, aPremultiplyAlpha},
SurfaceConfig{decoder, aSize, aOutputFormat, false});
}
TEST(ImageSwizzleFilter, WritePixels_RGBA_to_BGRA)
{
WithSwizzleFilter(
IntSize(100, 100), SurfaceFormat::R8G8B8A8, SurfaceFormat::B8G8R8A8,
false, [](Decoder* aDecoder, SurfaceFilter* aFilter) {
CheckTransformedWritePixels(aDecoder, aFilter, BGRAColor::Blue(),
BGRAColor::Red());
});
}
TEST(ImageSwizzleFilter, WritePixels_RGBA_to_Premultiplied_BGRA)
{
WithSwizzleFilter(
IntSize(100, 100), SurfaceFormat::R8G8B8A8, SurfaceFormat::B8G8R8A8, true,
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
CheckTransformedWritePixels(
aDecoder, aFilter, BGRAColor(0x26, 0x00, 0x00, 0x7F, true),
BGRAColor(0x00, 0x00, 0x26, 0x7F), Nothing(), Nothing(), Nothing(),
Nothing(), /* aFuzz */ 1);
});
}
TEST(ImageSwizzleFilter, WritePixels_RGBA_to_BGRX)
{
WithSwizzleFilter(
IntSize(100, 100), SurfaceFormat::R8G8B8A8, SurfaceFormat::B8G8R8X8,
false, [](Decoder* aDecoder, SurfaceFilter* aFilter) {
CheckTransformedWritePixels(aDecoder, aFilter,
BGRAColor(0x26, 0x00, 0x00, 0x7F, true),
BGRAColor(0x00, 0x00, 0x26, 0xFF));
});
}
TEST(ImageSwizzleFilter, WritePixels_RGBA_to_Premultiplied_BGRX)
{
WithSwizzleFilter(
IntSize(100, 100), SurfaceFormat::R8G8B8A8, SurfaceFormat::B8G8R8X8, true,
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
CheckTransformedWritePixels(aDecoder, aFilter,
BGRAColor(0x26, 0x00, 0x00, 0x7F, true),
BGRAColor(0x00, 0x00, 0x13, 0xFF));
});
}
TEST(ImageSwizzleFilter, WritePixels_RGBA_to_RGBX)
{
WithSwizzleFilter(
IntSize(100, 100), SurfaceFormat::R8G8B8A8, SurfaceFormat::R8G8B8X8,
false, [](Decoder* aDecoder, SurfaceFilter* aFilter) {
CheckTransformedWritePixels(aDecoder, aFilter,
BGRAColor(0x00, 0x00, 0x26, 0x7F, true),
BGRAColor(0x00, 0x00, 0x26, 0xFF));
});
}
TEST(ImageSwizzleFilter, WritePixels_RGBA_to_Premultiplied_RGRX)
{
WithSwizzleFilter(
IntSize(100, 100), SurfaceFormat::R8G8B8A8, SurfaceFormat::R8G8B8X8, true,
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
CheckTransformedWritePixels(aDecoder, aFilter,
BGRAColor(0x00, 0x00, 0x26, 0x7F, true),
BGRAColor(0x00, 0x00, 0x13, 0xFF));
});
}
TEST(ImageSwizzleFilter, WritePixels_BGRA_to_BGRX)
{
WithSwizzleFilter(
IntSize(100, 100), SurfaceFormat::B8G8R8A8, SurfaceFormat::B8G8R8X8,
false, [](Decoder* aDecoder, SurfaceFilter* aFilter) {
CheckTransformedWritePixels(aDecoder, aFilter,
BGRAColor(0x10, 0x26, 0x00, 0x7F, true),
BGRAColor(0x10, 0x26, 0x00, 0xFF));
});
}
TEST(ImageSwizzleFilter, WritePixels_BGRA_to_Premultiplied_BGRA)
{
WithSwizzleFilter(
IntSize(100, 100), SurfaceFormat::B8G8R8A8, SurfaceFormat::B8G8R8A8, true,
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
CheckTransformedWritePixels(
aDecoder, aFilter, BGRAColor(0x10, 0x26, 0x00, 0x7F, true),
BGRAColor(0x10, 0x26, 0x00, 0x7F), Nothing(), Nothing(), Nothing(),
Nothing(), /* aFuzz */ 1);
});
}

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

@ -19,6 +19,7 @@ UNIFIED_SOURCES = [
'TestRemoveFrameRectFilter.cpp',
'TestStreamingLexer.cpp',
'TestSurfaceSink.cpp',
'TestSwizzleFilter.cpp',
]
# skip the test on windows10-aarch64, aarch64 due to 1544961