зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1276061
(Part 4) - Add GTests for WriteBuffer() and WriteEmptyRow(). r=njn
--HG-- extra : rebase_source : 32628df4518af1fad89c69fa7aa5a87e3c325dc4
This commit is contained in:
Родитель
dfd4e97c3d
Коммит
2e1d5487fb
|
@ -42,6 +42,93 @@ private:
|
|||
} // namespace image
|
||||
} // namespace mozilla
|
||||
|
||||
void
|
||||
CheckSurfacePipeMethodResults(SurfacePipe* aPipe,
|
||||
Decoder* aDecoder,
|
||||
const IntRect& aRect = IntRect(0, 0, 100, 100))
|
||||
{
|
||||
// Check that the pipeline ended up in the state we expect. Note that we're
|
||||
// explicitly testing the SurfacePipe versions of these methods, so we don't
|
||||
// want to use AssertCorrectPipelineFinalState() here.
|
||||
EXPECT_TRUE(aPipe->IsSurfaceFinished());
|
||||
Maybe<SurfaceInvalidRect> invalidRect = aPipe->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isSome());
|
||||
EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mInputSpaceRect);
|
||||
EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mOutputSpaceRect);
|
||||
|
||||
// Check the generated image.
|
||||
CheckGeneratedImage(aDecoder, aRect);
|
||||
|
||||
// Reset and clear the image before the next test.
|
||||
aPipe->ResetToFirstRow();
|
||||
EXPECT_FALSE(aPipe->IsSurfaceFinished());
|
||||
invalidRect = aPipe->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
|
||||
uint32_t count = 0;
|
||||
auto result = aPipe->WritePixels<uint32_t>([&]() {
|
||||
++count;
|
||||
return AsVariant(BGRAColor::Transparent().AsPixel());
|
||||
});
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(100u * 100u, count);
|
||||
|
||||
EXPECT_TRUE(aPipe->IsSurfaceFinished());
|
||||
invalidRect = aPipe->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isSome());
|
||||
EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mInputSpaceRect);
|
||||
EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mOutputSpaceRect);
|
||||
|
||||
aPipe->ResetToFirstRow();
|
||||
EXPECT_FALSE(aPipe->IsSurfaceFinished());
|
||||
invalidRect = aPipe->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
}
|
||||
|
||||
void
|
||||
CheckPalettedSurfacePipeMethodResults(SurfacePipe* aPipe,
|
||||
Decoder* aDecoder,
|
||||
const IntRect& aRect
|
||||
= IntRect(0, 0, 100, 100))
|
||||
{
|
||||
// Check that the pipeline ended up in the state we expect. Note that we're
|
||||
// explicitly testing the SurfacePipe versions of these methods, so we don't
|
||||
// want to use AssertCorrectPipelineFinalState() here.
|
||||
EXPECT_TRUE(aPipe->IsSurfaceFinished());
|
||||
Maybe<SurfaceInvalidRect> invalidRect = aPipe->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isSome());
|
||||
EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mInputSpaceRect);
|
||||
EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mOutputSpaceRect);
|
||||
|
||||
// Check the generated image.
|
||||
CheckGeneratedPalettedImage(aDecoder, aRect);
|
||||
|
||||
// Reset and clear the image before the next test.
|
||||
aPipe->ResetToFirstRow();
|
||||
EXPECT_FALSE(aPipe->IsSurfaceFinished());
|
||||
invalidRect = aPipe->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
|
||||
uint32_t count = 0;
|
||||
auto result = aPipe->WritePixels<uint8_t>([&]() {
|
||||
++count;
|
||||
return AsVariant(uint8_t(0));
|
||||
});
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(100u * 100u, count);
|
||||
|
||||
EXPECT_TRUE(aPipe->IsSurfaceFinished());
|
||||
invalidRect = aPipe->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isSome());
|
||||
EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mInputSpaceRect);
|
||||
EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mOutputSpaceRect);
|
||||
|
||||
aPipe->ResetToFirstRow();
|
||||
EXPECT_FALSE(aPipe->IsSurfaceFinished());
|
||||
invalidRect = aPipe->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
}
|
||||
|
||||
TEST(ImageSurfacePipeIntegration, SurfacePipe)
|
||||
{
|
||||
// Test that SurfacePipe objects can be initialized and move constructed.
|
||||
|
@ -56,34 +143,152 @@ TEST(ImageSurfacePipeIntegration, SurfacePipe)
|
|||
|
||||
auto sink = MakeUnique<SurfaceSink>();
|
||||
nsresult rv =
|
||||
sink->Configure(SurfaceConfig { decoder.get(), 0, IntSize(100, 100),
|
||||
sink->Configure(SurfaceConfig { decoder, 0, IntSize(100, 100),
|
||||
SurfaceFormat::B8G8R8A8, false });
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
|
||||
pipe = TestSurfacePipeFactory::SurfacePipeFromPipeline(sink);
|
||||
|
||||
// Test that SurfacePipe passes through method calls to the underlying pipeline.
|
||||
int32_t count = 0;
|
||||
// Test that WritePixels() gets passed through to the underlying pipeline.
|
||||
{
|
||||
uint32_t count = 0;
|
||||
auto result = pipe.WritePixels<uint32_t>([&]() {
|
||||
++count;
|
||||
return AsVariant(BGRAColor::Green().AsPixel());
|
||||
});
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(100 * 100, count);
|
||||
EXPECT_EQ(100u * 100u, count);
|
||||
CheckSurfacePipeMethodResults(&pipe, decoder);
|
||||
}
|
||||
|
||||
// Note that we're explicitly testing the SurfacePipe versions of these
|
||||
// methods, so we don't want to use AssertCorrectPipelineFinalState() here.
|
||||
EXPECT_TRUE(pipe.IsSurfaceFinished());
|
||||
Maybe<SurfaceInvalidRect> invalidRect = pipe.TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isSome());
|
||||
EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mInputSpaceRect);
|
||||
EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mOutputSpaceRect);
|
||||
// Create a buffer the same size as one row of the surface, containing all
|
||||
// green pixels. We'll use this for the WriteBuffer() tests.
|
||||
uint32_t buffer[100];
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
buffer[i] = BGRAColor::Green().AsPixel();
|
||||
}
|
||||
|
||||
CheckGeneratedImage(decoder, IntRect(0, 0, 100, 100));
|
||||
// Test that WriteBuffer() gets passed through to the underlying pipeline.
|
||||
{
|
||||
uint32_t count = 0;
|
||||
WriteState result = WriteState::NEED_MORE_DATA;
|
||||
while (result == WriteState::NEED_MORE_DATA) {
|
||||
result = pipe.WriteBuffer(buffer);
|
||||
++count;
|
||||
}
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(100u, count);
|
||||
CheckSurfacePipeMethodResults(&pipe, decoder);
|
||||
}
|
||||
|
||||
pipe.ResetToFirstRow();
|
||||
EXPECT_FALSE(pipe.IsSurfaceFinished());
|
||||
// Test that the 3 argument version of WriteBuffer() gets passed through to
|
||||
// the underlying pipeline.
|
||||
{
|
||||
uint32_t count = 0;
|
||||
WriteState result = WriteState::NEED_MORE_DATA;
|
||||
while (result == WriteState::NEED_MORE_DATA) {
|
||||
result = pipe.WriteBuffer(buffer, 0, 100);
|
||||
++count;
|
||||
}
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(100u, count);
|
||||
CheckSurfacePipeMethodResults(&pipe, decoder);
|
||||
}
|
||||
|
||||
// Test that WriteEmptyRow() gets passed through to the underlying pipeline.
|
||||
{
|
||||
uint32_t count = 0;
|
||||
WriteState result = WriteState::NEED_MORE_DATA;
|
||||
while (result == WriteState::NEED_MORE_DATA) {
|
||||
result = pipe.WriteEmptyRow();
|
||||
++count;
|
||||
}
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(100u, count);
|
||||
CheckSurfacePipeMethodResults(&pipe, decoder, IntRect(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
// Mark the frame as finished so we don't get an assertion.
|
||||
RawAccessFrameRef currentFrame = decoder->GetCurrentFrameRef();
|
||||
currentFrame->Finish();
|
||||
}
|
||||
|
||||
TEST(ImageSurfacePipeIntegration, PalettedSurfacePipe)
|
||||
{
|
||||
// Create a SurfacePipe containing a PalettedSurfaceSink.
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
auto sink = MakeUnique<PalettedSurfaceSink>();
|
||||
nsresult rv =
|
||||
sink->Configure(PalettedSurfaceConfig { decoder, 0, IntSize(100, 100),
|
||||
IntRect(0, 0, 100, 100),
|
||||
SurfaceFormat::B8G8R8A8,
|
||||
8, false });
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
|
||||
SurfacePipe pipe = TestSurfacePipeFactory::SurfacePipeFromPipeline(sink);
|
||||
|
||||
// Test that WritePixels() gets passed through to the underlying pipeline.
|
||||
{
|
||||
uint32_t count = 0;
|
||||
auto result = pipe.WritePixels<uint8_t>([&]() {
|
||||
++count;
|
||||
return AsVariant(uint8_t(255));
|
||||
});
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(100u * 100u, count);
|
||||
CheckPalettedSurfacePipeMethodResults(&pipe, decoder);
|
||||
}
|
||||
|
||||
// Create a buffer the same size as one row of the surface, containing all
|
||||
// 255 pixels. We'll use this for the WriteBuffer() tests.
|
||||
uint8_t buffer[100];
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
buffer[i] = 255;
|
||||
}
|
||||
|
||||
// Test that WriteBuffer() gets passed through to the underlying pipeline.
|
||||
{
|
||||
uint32_t count = 0;
|
||||
WriteState result = WriteState::NEED_MORE_DATA;
|
||||
while (result == WriteState::NEED_MORE_DATA) {
|
||||
result = pipe.WriteBuffer(buffer);
|
||||
++count;
|
||||
}
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(100u, count);
|
||||
CheckPalettedSurfacePipeMethodResults(&pipe, decoder);
|
||||
}
|
||||
|
||||
// Test that the 3 argument version of WriteBuffer() gets passed through to
|
||||
// the underlying pipeline.
|
||||
{
|
||||
uint32_t count = 0;
|
||||
WriteState result = WriteState::NEED_MORE_DATA;
|
||||
while (result == WriteState::NEED_MORE_DATA) {
|
||||
result = pipe.WriteBuffer(buffer, 0, 100);
|
||||
++count;
|
||||
}
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(100u, count);
|
||||
CheckPalettedSurfacePipeMethodResults(&pipe, decoder);
|
||||
}
|
||||
|
||||
// Test that WriteEmptyRow() gets passed through to the underlying pipeline.
|
||||
{
|
||||
uint32_t count = 0;
|
||||
WriteState result = WriteState::NEED_MORE_DATA;
|
||||
while (result == WriteState::NEED_MORE_DATA) {
|
||||
result = pipe.WriteEmptyRow();
|
||||
++count;
|
||||
}
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(100u, count);
|
||||
CheckPalettedSurfacePipeMethodResults(&pipe, decoder, IntRect(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
// Mark the frame as finished so we don't get an assertion.
|
||||
RawAccessFrameRef currentFrame = decoder->GetCurrentFrameRef();
|
||||
currentFrame->Finish();
|
||||
}
|
||||
|
|
|
@ -48,6 +48,71 @@ WithPalettedSurfaceSink(const IntRect& aFrameRect, Func aFunc)
|
|||
8, false });
|
||||
}
|
||||
|
||||
void
|
||||
ResetForNextPass(SurfaceFilter* aSink)
|
||||
{
|
||||
aSink->ResetToFirstRow();
|
||||
EXPECT_FALSE(aSink->IsSurfaceFinished());
|
||||
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
}
|
||||
|
||||
template <typename WriteFunc, typename CheckFunc> void
|
||||
DoCheckIterativeWrite(SurfaceFilter* aSink,
|
||||
WriteFunc aWriteFunc,
|
||||
CheckFunc aCheckFunc)
|
||||
{
|
||||
// Write the buffer to successive rows until every row of the surface
|
||||
// has been written.
|
||||
uint32_t row = 0;
|
||||
WriteState result = WriteState::NEED_MORE_DATA;
|
||||
while (result == WriteState::NEED_MORE_DATA) {
|
||||
result = aWriteFunc(row);
|
||||
++row;
|
||||
}
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(100u, row);
|
||||
|
||||
AssertCorrectPipelineFinalState(aSink,
|
||||
IntRect(0, 0, 100, 100),
|
||||
IntRect(0, 0, 100, 100));
|
||||
|
||||
// Check that the generated image is correct.
|
||||
aCheckFunc();
|
||||
}
|
||||
|
||||
template <typename WriteFunc> void
|
||||
CheckIterativeWrite(Decoder* aDecoder,
|
||||
SurfaceSink* aSink,
|
||||
const IntRect& aOutputRect,
|
||||
WriteFunc aWriteFunc)
|
||||
{
|
||||
// Ignore the row passed to WriteFunc, since no callers use it.
|
||||
auto writeFunc = [&](uint32_t) {
|
||||
return aWriteFunc();
|
||||
};
|
||||
|
||||
DoCheckIterativeWrite(aSink, writeFunc, [&]{
|
||||
CheckGeneratedImage(aDecoder, aOutputRect);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename WriteFunc> void
|
||||
CheckPalettedIterativeWrite(Decoder* aDecoder,
|
||||
PalettedSurfaceSink* aSink,
|
||||
const IntRect& aOutputRect,
|
||||
WriteFunc aWriteFunc)
|
||||
{
|
||||
// Ignore the row passed to WriteFunc, since no callers use it.
|
||||
auto writeFunc = [&](uint32_t) {
|
||||
return aWriteFunc();
|
||||
};
|
||||
|
||||
DoCheckIterativeWrite(aSink, writeFunc, [&]{
|
||||
CheckGeneratedPalettedImage(aDecoder, aOutputRect);
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, NullSurfaceSink)
|
||||
{
|
||||
// Create the NullSurfaceSink.
|
||||
|
@ -68,9 +133,31 @@ TEST(ImageSurfaceSink, NullSurfaceSink)
|
|||
Maybe<SurfaceInvalidRect> invalidRect = sink.TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
|
||||
result = sink.WritePixels<uint32_t>([&]() {
|
||||
uint32_t source = BGRAColor::Red().AsPixel();
|
||||
result = sink.WriteBuffer(&source);
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_TRUE(sink.IsSurfaceFinished());
|
||||
invalidRect = sink.TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
|
||||
result = sink.WriteBuffer(&source, 0, 1);
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_TRUE(sink.IsSurfaceFinished());
|
||||
invalidRect = sink.TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
|
||||
result = sink.WriteEmptyRow();
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_TRUE(sink.IsSurfaceFinished());
|
||||
invalidRect = sink.TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
|
||||
result = sink.WriteUnsafeComputedRow<uint32_t>([&](uint32_t* aRow,
|
||||
uint32_t aLength) {
|
||||
gotCalled = true;
|
||||
return AsVariant(BGRAColor::Red().AsPixel());
|
||||
for (uint32_t col = 0; col < aLength; ++col, ++aRow) {
|
||||
*aRow = BGRAColor::Red().AsPixel();
|
||||
}
|
||||
});
|
||||
EXPECT_FALSE(gotCalled);
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
|
@ -145,6 +232,206 @@ TEST(ImageSurfaceSink, SurfaceSinkWritePixelsFinish)
|
|||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, SurfaceSinkWriteBuffer)
|
||||
{
|
||||
WithSurfaceSink<Orient::NORMAL>([](Decoder* aDecoder, SurfaceSink* aSink) {
|
||||
// Create a green buffer the same size as one row of the surface (which is 100x100),
|
||||
// containing 60 pixels of green in the middle and 20 transparent pixels on
|
||||
// either side.
|
||||
uint32_t buffer[100];
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
buffer[i] = 20 <= i && i < 80 ? BGRAColor::Green().AsPixel()
|
||||
: BGRAColor::Transparent().AsPixel();
|
||||
}
|
||||
|
||||
// Write the buffer to every row of the surface and check that the generated
|
||||
// image is correct.
|
||||
CheckIterativeWrite(aDecoder, aSink, IntRect(20, 0, 60, 100), [&]{
|
||||
return aSink->WriteBuffer(buffer);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, SurfaceSinkWriteBufferPartialRow)
|
||||
{
|
||||
WithSurfaceSink<Orient::NORMAL>([](Decoder* aDecoder, SurfaceSink* aSink) {
|
||||
// Create a buffer the same size as one row of the surface, containing all
|
||||
// green pixels.
|
||||
uint32_t buffer[100];
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
buffer[i] = BGRAColor::Green().AsPixel();
|
||||
}
|
||||
|
||||
// Write the buffer to the middle 60 pixels of every row of the surface and
|
||||
// check that the generated image is correct.
|
||||
CheckIterativeWrite(aDecoder, aSink, IntRect(20, 0, 60, 100), [&]{
|
||||
return aSink->WriteBuffer(buffer, 20, 60);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, SurfaceSinkWriteBufferPartialRowStartColOverflow)
|
||||
{
|
||||
WithSurfaceSink<Orient::NORMAL>([](Decoder* aDecoder, SurfaceSink* aSink) {
|
||||
// Create a buffer the same size as one row of the surface, containing all
|
||||
// green pixels.
|
||||
uint32_t buffer[100];
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
buffer[i] = BGRAColor::Green().AsPixel();
|
||||
}
|
||||
|
||||
{
|
||||
// Write the buffer to successive rows until every row of the surface
|
||||
// has been written. We place the start column beyond the end of the row,
|
||||
// which will prevent us from writing anything, so we check that the
|
||||
// generated image is entirely transparent.
|
||||
CheckIterativeWrite(aDecoder, aSink, IntRect(0, 0, 0, 0), [&]{
|
||||
return aSink->WriteBuffer(buffer, 100, 100);
|
||||
});
|
||||
}
|
||||
|
||||
ResetForNextPass(aSink);
|
||||
|
||||
{
|
||||
// Write the buffer to successive rows until every row of the surface
|
||||
// has been written. We use column 50 as the start column, but we still
|
||||
// write the buffer, which means we overflow the right edge of the surface
|
||||
// by 50 pixels. We check that the left half of the generated image is
|
||||
// transparent and the right half is green.
|
||||
CheckIterativeWrite(aDecoder, aSink, IntRect(50, 0, 50, 100), [&]{
|
||||
return aSink->WriteBuffer(buffer, 50, 100);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, SurfaceSinkWriteBufferPartialRowBufferOverflow)
|
||||
{
|
||||
WithSurfaceSink<Orient::NORMAL>([](Decoder* aDecoder, SurfaceSink* aSink) {
|
||||
// Create a buffer twice as large as a row of the surface. The first half
|
||||
// (which is as large as a row of the image) will contain green pixels,
|
||||
// while the second half will contain red pixels.
|
||||
uint32_t buffer[200];
|
||||
for (int i = 0; i < 200; ++i) {
|
||||
buffer[i] = i < 100 ? BGRAColor::Green().AsPixel()
|
||||
: BGRAColor::Red().AsPixel();
|
||||
}
|
||||
|
||||
{
|
||||
// Write the buffer to successive rows until every row of the surface has
|
||||
// been written. The buffer extends 100 pixels to the right of a row of
|
||||
// the surface, but bounds checking will prevent us from overflowing the
|
||||
// buffer. We check that the generated image is entirely green since the
|
||||
// pixels on the right side of the buffer shouldn't have been written to
|
||||
// the surface.
|
||||
CheckIterativeWrite(aDecoder, aSink, IntRect(0, 0, 100, 100), [&]{
|
||||
return aSink->WriteBuffer(buffer, 0, 200);
|
||||
});
|
||||
}
|
||||
|
||||
ResetForNextPass(aSink);
|
||||
|
||||
{
|
||||
// Write from the buffer to the middle of each row of the surface. That
|
||||
// means that the left side of each row should be transparent, since we
|
||||
// didn't write anything there. A buffer overflow would cause us to write
|
||||
// buffer contents into the left side of each row. We check that the
|
||||
// generated image is transparent on the left side and green on the right.
|
||||
CheckIterativeWrite(aDecoder, aSink, IntRect(50, 0, 50, 100), [&]{
|
||||
return aSink->WriteBuffer(buffer, 50, 200);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, SurfaceSinkWriteBufferFromNullSource)
|
||||
{
|
||||
WithSurfaceSink<Orient::NORMAL>([](Decoder* aDecoder, SurfaceSink* aSink) {
|
||||
// Calling WriteBuffer() with a null pointer should fail without making any
|
||||
// changes to the surface.
|
||||
uint32_t* nullBuffer = nullptr;
|
||||
WriteState result = aSink->WriteBuffer(nullBuffer);
|
||||
|
||||
EXPECT_EQ(WriteState::FAILURE, result);
|
||||
EXPECT_FALSE(aSink->IsSurfaceFinished());
|
||||
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
|
||||
// Check that nothing got written to the surface.
|
||||
CheckGeneratedImage(aDecoder, IntRect(0, 0, 0, 0));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, SurfaceSinkWriteEmptyRow)
|
||||
{
|
||||
WithSurfaceSink<Orient::NORMAL>([](Decoder* aDecoder, SurfaceSink* aSink) {
|
||||
{
|
||||
// Write an empty row to each row of the surface. We check that the
|
||||
// generated image is entirely transparent.
|
||||
CheckIterativeWrite(aDecoder, aSink, IntRect(0, 0, 0, 0), [&]{
|
||||
return aSink->WriteEmptyRow();
|
||||
});
|
||||
}
|
||||
|
||||
ResetForNextPass(aSink);
|
||||
|
||||
{
|
||||
// Create a buffer the same size as one row of the surface, containing all
|
||||
// green pixels.
|
||||
uint32_t buffer[100];
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
buffer[i] = BGRAColor::Green().AsPixel();
|
||||
}
|
||||
|
||||
// Write an empty row to the middle 60 rows of the surface. The first 20
|
||||
// and last 20 rows will be green. (We need to use DoCheckIterativeWrite()
|
||||
// here because we need a custom function to check the output, since it
|
||||
// can't be described by a simple rect.)
|
||||
auto writeFunc = [&](uint32_t aRow) {
|
||||
if (aRow < 20 || aRow >= 80) {
|
||||
return aSink->WriteBuffer(buffer);
|
||||
} else {
|
||||
return aSink->WriteEmptyRow();
|
||||
}
|
||||
};
|
||||
|
||||
auto checkFunc = [&]{
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
RefPtr<SourceSurface> surface = currentFrame->GetSurface();
|
||||
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, 0, 20, BGRAColor::Green()));
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, 20, 60, BGRAColor::Transparent()));
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, 80, 20, BGRAColor::Green()));
|
||||
};
|
||||
|
||||
DoCheckIterativeWrite(aSink, writeFunc, checkFunc);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, SurfaceSinkWriteUnsafeComputedRow)
|
||||
{
|
||||
WithSurfaceSink<Orient::NORMAL>([](Decoder* aDecoder, SurfaceSink* aSink) {
|
||||
// Create a green buffer the same size as one row of the surface.
|
||||
uint32_t buffer[100];
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
buffer[i] = BGRAColor::Green().AsPixel();
|
||||
}
|
||||
|
||||
// Write the buffer to successive rows until every row of the surface
|
||||
// has been written. We only write to the right half of each row, so we
|
||||
// check that the left side of the generated image is transparent and the
|
||||
// right side is green.
|
||||
CheckIterativeWrite(aDecoder, aSink, IntRect(50, 0, 50, 100), [&]{
|
||||
return aSink->WriteUnsafeComputedRow<uint32_t>([&](uint32_t* aRow,
|
||||
uint32_t aLength) {
|
||||
EXPECT_EQ(100u, aLength );
|
||||
memcpy(aRow + 50, buffer, 50 * sizeof(uint32_t));
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, SurfaceSinkProgressivePasses)
|
||||
{
|
||||
WithSurfaceSink<Orient::NORMAL>([](Decoder* aDecoder, SurfaceSink* aSink) {
|
||||
|
@ -169,11 +456,7 @@ TEST(ImageSurfaceSink, SurfaceSinkProgressivePasses)
|
|||
}
|
||||
|
||||
{
|
||||
// Reset for the second pass.
|
||||
aSink->ResetToFirstRow();
|
||||
EXPECT_FALSE(aSink->IsSurfaceFinished());
|
||||
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
ResetForNextPass(aSink);
|
||||
|
||||
// Check that the generated image is still the first pass image.
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
|
@ -353,11 +636,7 @@ TEST(ImageSurfaceSink, SurfaceSinkFlipVertically)
|
|||
}
|
||||
|
||||
{
|
||||
// Reset for the second pass.
|
||||
aSink->ResetToFirstRow();
|
||||
EXPECT_FALSE(aSink->IsSurfaceFinished());
|
||||
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
ResetForNextPass(aSink);
|
||||
|
||||
// Check that the generated image is still the first pass image.
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
|
@ -504,3 +783,204 @@ TEST(ImageSurfaceSink, PalettedSurfaceSinkWritePixelsFor75_75_50_50)
|
|||
/* aOutputWriteRect = */ Some(IntRect(75, 75, 50, 50)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteBuffer)
|
||||
{
|
||||
WithPalettedSurfaceSink(IntRect(0, 0, 100, 100),
|
||||
[](Decoder* aDecoder, PalettedSurfaceSink* aSink) {
|
||||
// Create a buffer the same size as one row of the surface (which is 100x100),
|
||||
// containing 60 pixels of 255 in the middle and 20 transparent pixels of 0 on
|
||||
// either side.
|
||||
uint8_t buffer[100];
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
buffer[i] = 20 <= i && i < 80 ? 255 : 0;
|
||||
}
|
||||
|
||||
// Write the buffer to every row of the surface and check that the generated
|
||||
// image is correct.
|
||||
CheckPalettedIterativeWrite(aDecoder, aSink, IntRect(20, 0, 60, 100), [&]{
|
||||
return aSink->WriteBuffer(buffer);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteBufferPartialRow)
|
||||
{
|
||||
WithPalettedSurfaceSink(IntRect(0, 0, 100, 100),
|
||||
[](Decoder* aDecoder, PalettedSurfaceSink* aSink) {
|
||||
// Create a buffer the same size as one row of the surface, containing all
|
||||
// 255 pixels.
|
||||
uint8_t buffer[100];
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
buffer[i] = 255;
|
||||
}
|
||||
|
||||
// Write the buffer to the middle 60 pixels of every row of the surface and
|
||||
// check that the generated image is correct.
|
||||
CheckPalettedIterativeWrite(aDecoder, aSink, IntRect(20, 0, 60, 100), [&]{
|
||||
return aSink->WriteBuffer(buffer, 20, 60);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteBufferPartialRowStartColOverflow)
|
||||
{
|
||||
WithPalettedSurfaceSink(IntRect(0, 0, 100, 100),
|
||||
[](Decoder* aDecoder, PalettedSurfaceSink* aSink) {
|
||||
// Create a buffer the same size as one row of the surface, containing all
|
||||
// 255 pixels.
|
||||
uint8_t buffer[100];
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
buffer[i] = 255;
|
||||
}
|
||||
|
||||
{
|
||||
// Write the buffer to successive rows until every row of the surface
|
||||
// has been written. We place the start column beyond the end of the row,
|
||||
// which will prevent us from writing anything, so we check that the
|
||||
// generated image is entirely 0.
|
||||
CheckPalettedIterativeWrite(aDecoder, aSink, IntRect(0, 0, 0, 0), [&]{
|
||||
return aSink->WriteBuffer(buffer, 100, 100);
|
||||
});
|
||||
}
|
||||
|
||||
ResetForNextPass(aSink);
|
||||
|
||||
{
|
||||
// Write the buffer to successive rows until every row of the surface
|
||||
// has been written. We use column 50 as the start column, but we still
|
||||
// write the buffer, which means we overflow the right edge of the surface
|
||||
// by 50 pixels. We check that the left half of the generated image is
|
||||
// 0 and the right half is 255.
|
||||
CheckPalettedIterativeWrite(aDecoder, aSink, IntRect(50, 0, 50, 100), [&]{
|
||||
return aSink->WriteBuffer(buffer, 50, 100);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteBufferPartialRowBufferOverflow)
|
||||
{
|
||||
WithPalettedSurfaceSink(IntRect(0, 0, 100, 100),
|
||||
[](Decoder* aDecoder, PalettedSurfaceSink* aSink) {
|
||||
// Create a buffer twice as large as a row of the surface. The first half
|
||||
// (which is as large as a row of the image) will contain 255 pixels,
|
||||
// while the second half will contain 128 pixels.
|
||||
uint8_t buffer[200];
|
||||
for (int i = 0; i < 200; ++i) {
|
||||
buffer[i] = i < 100 ? 255 : 128;
|
||||
}
|
||||
|
||||
{
|
||||
// Write the buffer to successive rows until every row of the surface has
|
||||
// been written. The buffer extends 100 pixels to the right of a row of
|
||||
// the surface, but bounds checking will prevent us from overflowing the
|
||||
// buffer. We check that the generated image is entirely 255 since the
|
||||
// pixels on the right side of the buffer shouldn't have been written to
|
||||
// the surface.
|
||||
CheckPalettedIterativeWrite(aDecoder, aSink, IntRect(0, 0, 100, 100), [&]{
|
||||
return aSink->WriteBuffer(buffer, 0, 200);
|
||||
});
|
||||
}
|
||||
|
||||
ResetForNextPass(aSink);
|
||||
|
||||
{
|
||||
// Write from the buffer to the middle of each row of the surface. That
|
||||
// means that the left side of each row should be 0, since we didn't write
|
||||
// anything there. A buffer overflow would cause us to write buffer
|
||||
// contents into the left side of each row. We check that the generated
|
||||
// image is 0 on the left side and 255 on the right.
|
||||
CheckPalettedIterativeWrite(aDecoder, aSink, IntRect(50, 0, 50, 100), [&]{
|
||||
return aSink->WriteBuffer(buffer, 50, 200);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteBufferFromNullSource)
|
||||
{
|
||||
WithPalettedSurfaceSink(IntRect(0, 0, 100, 100),
|
||||
[](Decoder* aDecoder, PalettedSurfaceSink* aSink) {
|
||||
// Calling WriteBuffer() with a null pointer should fail without making any
|
||||
// changes to the surface.
|
||||
uint8_t* nullBuffer = nullptr;
|
||||
WriteState result = aSink->WriteBuffer(nullBuffer);
|
||||
|
||||
EXPECT_EQ(WriteState::FAILURE, result);
|
||||
EXPECT_FALSE(aSink->IsSurfaceFinished());
|
||||
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
|
||||
// Check that nothing got written to the surface.
|
||||
CheckGeneratedPalettedImage(aDecoder, IntRect(0, 0, 0, 0));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteEmptyRow)
|
||||
{
|
||||
WithPalettedSurfaceSink(IntRect(0, 0, 100, 100),
|
||||
[](Decoder* aDecoder, PalettedSurfaceSink* aSink) {
|
||||
{
|
||||
// Write an empty row to each row of the surface. We check that the
|
||||
// generated image is entirely 0.
|
||||
CheckPalettedIterativeWrite(aDecoder, aSink, IntRect(0, 0, 0, 0), [&]{
|
||||
return aSink->WriteEmptyRow();
|
||||
});
|
||||
}
|
||||
|
||||
ResetForNextPass(aSink);
|
||||
|
||||
{
|
||||
// Create a buffer the same size as one row of the surface, containing all
|
||||
// 255 pixels.
|
||||
uint8_t buffer[100];
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
buffer[i] = 255;
|
||||
}
|
||||
|
||||
// Write an empty row to the middle 60 rows of the surface. The first 20
|
||||
// and last 20 rows will be 255. (We need to use DoCheckIterativeWrite()
|
||||
// here because we need a custom function to check the output, since it
|
||||
// can't be described by a simple rect.)
|
||||
auto writeFunc = [&](uint32_t aRow) {
|
||||
if (aRow < 20 || aRow >= 80) {
|
||||
return aSink->WriteBuffer(buffer);
|
||||
} else {
|
||||
return aSink->WriteEmptyRow();
|
||||
}
|
||||
};
|
||||
|
||||
auto checkFunc = [&]{
|
||||
EXPECT_TRUE(PalettedRowsAreSolidColor(aDecoder, 0, 20, 255));
|
||||
EXPECT_TRUE(PalettedRowsAreSolidColor(aDecoder, 20, 60, 0));
|
||||
EXPECT_TRUE(PalettedRowsAreSolidColor(aDecoder, 80, 20, 255));
|
||||
};
|
||||
|
||||
DoCheckIterativeWrite(aSink, writeFunc, checkFunc);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteUnsafeComputedRow)
|
||||
{
|
||||
WithPalettedSurfaceSink(IntRect(0, 0, 100, 100),
|
||||
[](Decoder* aDecoder, PalettedSurfaceSink* aSink) {
|
||||
// Create an all-255 buffer the same size as one row of the surface.
|
||||
uint8_t buffer[100];
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
buffer[i] = 255;
|
||||
}
|
||||
|
||||
// Write the buffer to successive rows until every row of the surface has
|
||||
// been written. We only write to the right half of each row, so we check
|
||||
// that the left side of the generated image is 0 and the right side is 255.
|
||||
CheckPalettedIterativeWrite(aDecoder, aSink, IntRect(50, 0, 50, 100), [&]{
|
||||
return aSink->WriteUnsafeComputedRow<uint8_t>([&](uint8_t* aRow,
|
||||
uint32_t aLength) {
|
||||
EXPECT_EQ(100u, aLength );
|
||||
memcpy(aRow + 50, buffer, 50 * sizeof(uint8_t));
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче