diff options
Diffstat (limited to '')
-rw-r--r-- | gfx/2d/unittest/Main.cpp | 51 | ||||
-rw-r--r-- | gfx/2d/unittest/SanityChecks.cpp | 15 | ||||
-rw-r--r-- | gfx/2d/unittest/SanityChecks.h | 16 | ||||
-rw-r--r-- | gfx/2d/unittest/TestBase.cpp | 44 | ||||
-rw-r--r-- | gfx/2d/unittest/TestBase.h | 53 | ||||
-rw-r--r-- | gfx/2d/unittest/TestBugs.cpp | 80 | ||||
-rw-r--r-- | gfx/2d/unittest/TestBugs.h | 17 | ||||
-rw-r--r-- | gfx/2d/unittest/TestCairo.cpp | 99 | ||||
-rw-r--r-- | gfx/2d/unittest/TestDrawTargetBase.cpp | 103 | ||||
-rw-r--r-- | gfx/2d/unittest/TestDrawTargetBase.h | 38 | ||||
-rw-r--r-- | gfx/2d/unittest/TestDrawTargetD2D.cpp | 22 | ||||
-rw-r--r-- | gfx/2d/unittest/TestDrawTargetD2D.h | 19 | ||||
-rw-r--r-- | gfx/2d/unittest/TestPoint.cpp | 42 | ||||
-rw-r--r-- | gfx/2d/unittest/TestPoint.h | 17 | ||||
-rw-r--r-- | gfx/2d/unittest/TestScaling.cpp | 235 | ||||
-rw-r--r-- | gfx/2d/unittest/TestScaling.h | 22 | ||||
-rw-r--r-- | gfx/2d/unittest/unittest.vcxproj | 94 |
17 files changed, 967 insertions, 0 deletions
diff --git a/gfx/2d/unittest/Main.cpp b/gfx/2d/unittest/Main.cpp new file mode 100644 index 0000000000..0a6c9b0401 --- /dev/null +++ b/gfx/2d/unittest/Main.cpp @@ -0,0 +1,51 @@ +/* -*- 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 "SanityChecks.h" +#include "TestPoint.h" +#include "TestScaling.h" +#include "TestBugs.h" +#ifdef WIN32 +# include "TestDrawTargetD2D.h" +#endif + +#include <string> +#include <sstream> + +struct TestObject { + TestBase* test; + std::string name; +}; + +int main() { + TestObject tests[] = { + {new SanityChecks(), "Sanity Checks"}, +#ifdef WIN32 + {new TestDrawTargetD2D(), "DrawTarget (D2D)"}, +#endif + {new TestPoint(), "Point Tests"}, + {new TestScaling(), "Scaling Tests"} {new TestBugs(), "Bug Tests"}}; + + int totalFailures = 0; + int totalTests = 0; + std::stringstream message; + printf("------ STARTING RUNNING TESTS ------\n"); + for (int i = 0; i < sizeof(tests) / sizeof(TestObject); i++) { + message << "--- RUNNING TESTS: " << tests[i].name << " ---\n"; + printf(message.str().c_str()); + message.str(""); + int failures = 0; + totalTests += tests[i].test->RunTests(&failures); + totalFailures += failures; + // Done with this test! + delete tests[i].test; + } + message << "------ FINISHED RUNNING TESTS ------\nTests run: " << totalTests + << " - Passes: " << totalTests - totalFailures + << " - Failures: " << totalFailures << "\n"; + printf(message.str().c_str()); + return totalFailures; +} diff --git a/gfx/2d/unittest/SanityChecks.cpp b/gfx/2d/unittest/SanityChecks.cpp new file mode 100644 index 0000000000..c8db1dd69d --- /dev/null +++ b/gfx/2d/unittest/SanityChecks.cpp @@ -0,0 +1,15 @@ +/* -*- 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 "SanityChecks.h" + +SanityChecks::SanityChecks() { REGISTER_TEST(SanityChecks, AlwaysPasses); } + +void SanityChecks::AlwaysPasses() { + bool testMustPass = true; + + VERIFY(testMustPass); +} diff --git a/gfx/2d/unittest/SanityChecks.h b/gfx/2d/unittest/SanityChecks.h new file mode 100644 index 0000000000..6161b783eb --- /dev/null +++ b/gfx/2d/unittest/SanityChecks.h @@ -0,0 +1,16 @@ +/* -*- 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/. */ + +#pragma once + +#include "TestBase.h" + +class SanityChecks : public TestBase { + public: + SanityChecks(); + + void AlwaysPasses(); +}; diff --git a/gfx/2d/unittest/TestBase.cpp b/gfx/2d/unittest/TestBase.cpp new file mode 100644 index 0000000000..bf78008489 --- /dev/null +++ b/gfx/2d/unittest/TestBase.cpp @@ -0,0 +1,44 @@ +/* -*- 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 "TestBase.h" + +#include <sstream> + +int TestBase::RunTests(int* aFailures) { + int testsRun = 0; + *aFailures = 0; + + for (unsigned int i = 0; i < mTests.size(); i++) { + std::stringstream stream; + stream << "Test (" << mTests[i].name << "): "; + LogMessage(stream.str()); + stream.str(""); + + mTestFailed = false; + + // Don't try this at home! We know these are actually pointers to members + // of child clases, so we reinterpret cast those child class pointers to + // TestBase and then call the functions. Because the compiler believes + // these function calls are members of TestBase. + ((*reinterpret_cast<TestBase*>((mTests[i].implPointer))).* + (mTests[i].funcCall))(); + + if (!mTestFailed) { + LogMessage("PASSED\n"); + } else { + LogMessage("FAILED\n"); + (*aFailures)++; + } + testsRun++; + } + + return testsRun; +} + +void TestBase::LogMessage(std::string aMessage) { + printf("%s", aMessage.c_str()); +} diff --git a/gfx/2d/unittest/TestBase.h b/gfx/2d/unittest/TestBase.h new file mode 100644 index 0000000000..fb9326e856 --- /dev/null +++ b/gfx/2d/unittest/TestBase.h @@ -0,0 +1,53 @@ +/* -*- 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/. */ + +#pragma once + +#include <string> +#include <vector> + +#if defined(_MSC_VER) && !defined(__clang__) +// On MSVC otherwise our generic member pointer trick doesn't work. +// JYA: Do we still need this? +# pragma pointers_to_members(full_generality, single_inheritance) +#endif + +#define VERIFY(arg) \ + if (!(arg)) { \ + LogMessage("VERIFY FAILED: " #arg "\n"); \ + mTestFailed = true; \ + } + +#define REGISTER_TEST(className, testName) \ + mTests.push_back( \ + Test(static_cast<TestCall>(&className::testName), #testName, this)) + +class TestBase { + public: + TestBase() = default; + + typedef void (TestBase::*TestCall)(); + + int RunTests(int* aFailures); + + protected: + static void LogMessage(std::string aMessage); + + struct Test { + Test(TestCall aCall, std::string aName, void* aImplPointer) + : funcCall(aCall), name(aName), implPointer(aImplPointer) {} + TestCall funcCall; + std::string name; + void* implPointer; + }; + std::vector<Test> mTests; + + bool mTestFailed; + + private: + // This doesn't really work with our generic member pointer trick. + TestBase(const TestBase& aOther); +}; diff --git a/gfx/2d/unittest/TestBugs.cpp b/gfx/2d/unittest/TestBugs.cpp new file mode 100644 index 0000000000..545166007a --- /dev/null +++ b/gfx/2d/unittest/TestBugs.cpp @@ -0,0 +1,80 @@ +/* -*- 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 "TestBugs.h" +#include "2D.h" +#include <string.h> + +using namespace mozilla; +using namespace mozilla::gfx; + +TestBugs::TestBugs() { + REGISTER_TEST(TestBugs, CairoClip918671); + REGISTER_TEST(TestBugs, PushPopClip950550); +} + +void TestBugs::CairoClip918671() { + RefPtr<DrawTarget> dt = Factory::CreateDrawTarget( + BackendType::CAIRO, IntSize(100, 100), SurfaceFormat::B8G8R8A8); + RefPtr<DrawTarget> ref = Factory::CreateDrawTarget( + BackendType::CAIRO, IntSize(100, 100), SurfaceFormat::B8G8R8A8); + // Create a path that extends around the center rect but doesn't intersect it. + RefPtr<PathBuilder> pb1 = dt->CreatePathBuilder(); + pb1->MoveTo(Point(10, 10)); + pb1->LineTo(Point(90, 10)); + pb1->LineTo(Point(90, 20)); + pb1->LineTo(Point(10, 20)); + pb1->Close(); + pb1->MoveTo(Point(90, 90)); + pb1->LineTo(Point(91, 90)); + pb1->LineTo(Point(91, 91)); + pb1->LineTo(Point(91, 90)); + pb1->Close(); + + RefPtr<Path> path1 = pb1->Finish(); + dt->PushClip(path1); + + // This center rect must NOT be rectilinear! + RefPtr<PathBuilder> pb2 = dt->CreatePathBuilder(); + pb2->MoveTo(Point(50, 50)); + pb2->LineTo(Point(55, 51)); + pb2->LineTo(Point(54, 55)); + pb2->LineTo(Point(50, 56)); + pb2->Close(); + + RefPtr<Path> path2 = pb2->Finish(); + dt->PushClip(path2); + + dt->FillRect(Rect(0, 0, 100, 100), ColorPattern(DeviceColor(1, 0, 0))); + + RefPtr<SourceSurface> surf1 = dt->Snapshot(); + RefPtr<SourceSurface> surf2 = ref->Snapshot(); + + RefPtr<DataSourceSurface> dataSurf1 = surf1->GetDataSurface(); + RefPtr<DataSourceSurface> dataSurf2 = surf2->GetDataSurface(); + + DataSourceSurface::ScopedMap map1(dataSurf1, DataSourceSurface::READ); + DataSourceSurface::ScopedMap map2(dataSurf2, DataSourceSurface::READ); + for (int y = 0; y < dt->GetSize().height; y++) { + VERIFY(memcmp(map1.GetData() + y * map1.GetStride(), + map2.GetData() + y * map2.GetStride(), + dataSurf1->GetSize().width * 4) == 0); + } +} + +void TestBugs::PushPopClip950550() { + RefPtr<DrawTarget> dt = Factory::CreateDrawTarget( + BackendType::CAIRO, IntSize(500, 500), SurfaceFormat::B8G8R8A8); + dt->PushClipRect(Rect(0, 0, 100, 100)); + Matrix m(1, 0, 0, 1, 45, -100); + dt->SetTransform(m); + dt->PopClip(); + + // We fail the test if we assert in this call because our draw target's + // transforms are out of sync. + dt->FillRect(Rect(50, 50, 50, 50), + ColorPattern(DeviceColor(0.5f, 0, 0, 1.0f))); +} diff --git a/gfx/2d/unittest/TestBugs.h b/gfx/2d/unittest/TestBugs.h new file mode 100644 index 0000000000..c337b05cff --- /dev/null +++ b/gfx/2d/unittest/TestBugs.h @@ -0,0 +1,17 @@ +/* -*- 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/. */ + +#pragma once + +#include "TestBase.h" + +class TestBugs : public TestBase { + public: + TestBugs(); + + void CairoClip918671(); + void PushPopClip950550(); +}; diff --git a/gfx/2d/unittest/TestCairo.cpp b/gfx/2d/unittest/TestCairo.cpp new file mode 100644 index 0000000000..4ed7ad4d4a --- /dev/null +++ b/gfx/2d/unittest/TestCairo.cpp @@ -0,0 +1,99 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +#include "cairo.h" + +#include "gtest/gtest.h" + +namespace mozilla { +namespace layers { + +static void TryCircle(double centerX, double centerY, double radius) { + printf("TestCairo:TryArcs centerY %f, radius %f\n", centerY, radius); + + cairo_surface_t* surf = + cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 8, 21); + ASSERT_TRUE(surf != nullptr); + + cairo_t* cairo = cairo_create(surf); + ASSERT_TRUE(cairo != nullptr); + + cairo_set_antialias(cairo, CAIRO_ANTIALIAS_NONE); + cairo_arc(cairo, 0.0, centerY, radius, 0.0, 6.2831853071795862); + cairo_fill_preserve(cairo); + + cairo_surface_destroy(surf); + cairo_destroy(cairo); +} + +TEST(Cairo, Simple) +{ + TryCircle(0.0, 0.0, 14.0); + TryCircle(0.0, 1.0, 22.4); + TryCircle(1.0, 0.0, 1422.4); + TryCircle(1.0, 1.0, 3422.4); + TryCircle(-10.0, 1.0, -2); +} + +TEST(Cairo, Bug825721) +{ + // OK: + TryCircle(0.0, 0.0, 8761126469220696064.0); + TryCircle(0.0, 1.0, 8761126469220696064.0); + + // OK: + TryCircle(1.0, 0.0, 5761126469220696064.0); + + // This was the crash in 825721. Note that centerY has to be non-zero, + // and radius has to be not only large, but in particular range. + // 825721 has a band-aid fix, where the crash is inevitable, but does + // not fix the cause. The same code crashes in cairo standalone. + TryCircle(0.0, 1.0, 5761126469220696064.0); +} + +TEST(Cairo, Bug1063486) +{ + double x1, y1, x2, y2; + const double epsilon = .01; + + cairo_surface_t* surf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1); + ASSERT_TRUE(surf != nullptr); + + cairo_t* cairo = cairo_create(surf); + ASSERT_TRUE(cairo != nullptr); + + printf("Path 1\n"); + cairo_move_to(cairo, -20, -10); + cairo_line_to(cairo, 20, -10); + cairo_line_to(cairo, 20, 10); + cairo_curve_to(cairo, 10, 10, -10, 10, -20, 10); + cairo_curve_to(cairo, -30, 10, -30, -10, -20, -10); + + cairo_path_extents(cairo, &x1, &y1, &x2, &y2); + + ASSERT_LT(std::abs(-27.5 - x1), epsilon); // the failing coordinate + ASSERT_LT(std::abs(-10 - y1), epsilon); + ASSERT_LT(std::abs(20 - x2), epsilon); + ASSERT_LT(std::abs(10 - y2), epsilon); + + printf("Path 2\n"); + cairo_new_path(cairo); + cairo_move_to(cairo, 10, 30); + cairo_line_to(cairo, 90, 30); + cairo_curve_to(cairo, 30, 30, 30, 30, 10, 30); + cairo_curve_to(cairo, 0, 30, 0, 0, 30, 5); + + cairo_path_extents(cairo, &x1, &y1, &x2, &y2); + + ASSERT_LT(std::abs(4.019531 - x1), epsilon); // the failing coordinate + ASSERT_LT(std::abs(4.437500 - y1), epsilon); + ASSERT_LT(std::abs(90. - x2), epsilon); + ASSERT_LT(std::abs(30. - y2), epsilon); + + cairo_surface_destroy(surf); + cairo_destroy(cairo); +} + +} // namespace layers +} // namespace mozilla diff --git a/gfx/2d/unittest/TestDrawTargetBase.cpp b/gfx/2d/unittest/TestDrawTargetBase.cpp new file mode 100644 index 0000000000..2ef817cd86 --- /dev/null +++ b/gfx/2d/unittest/TestDrawTargetBase.cpp @@ -0,0 +1,103 @@ +/* -*- 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 "TestDrawTargetBase.h" +#include <sstream> + +using namespace mozilla; +using namespace mozilla::gfx; + +TestDrawTargetBase::TestDrawTargetBase() { + REGISTER_TEST(TestDrawTargetBase, Initialized); + REGISTER_TEST(TestDrawTargetBase, FillCompletely); + REGISTER_TEST(TestDrawTargetBase, FillRect); +} + +void TestDrawTargetBase::Initialized() { VERIFY(mDT); } + +void TestDrawTargetBase::FillCompletely() { + mDT->FillRect(Rect(0, 0, DT_WIDTH, DT_HEIGHT), + ColorPattern(DeviceColor(0, 0.5f, 0, 1.0f))); + + RefreshSnapshot(); + + VerifyAllPixels(DeviceColor(0, 0.5f, 0, 1.0f)); +} + +void TestDrawTargetBase::FillRect() { + mDT->FillRect(Rect(0, 0, DT_WIDTH, DT_HEIGHT), + ColorPattern(DeviceColor(0, 0.5f, 0, 1.0f))); + mDT->FillRect(Rect(50, 50, 50, 50), + ColorPattern(DeviceColor(0.5f, 0, 0, 1.0f))); + + RefreshSnapshot(); + + VerifyPixel(IntPoint(49, 49), DeviceColor(0, 0.5f, 0, 1.0f)); + VerifyPixel(IntPoint(50, 50), DeviceColor(0.5f, 0, 0, 1.0f)); + VerifyPixel(IntPoint(99, 99), DeviceColor(0.5f, 0, 0, 1.0f)); + VerifyPixel(IntPoint(100, 100), DeviceColor(0, 0.5f, 0, 1.0f)); +} + +void TestDrawTargetBase::RefreshSnapshot() { + RefPtr<SourceSurface> snapshot = mDT->Snapshot(); + mDataSnapshot = snapshot->GetDataSurface(); +} + +void TestDrawTargetBase::VerifyAllPixels(const DeviceColor& aColor) { + uint32_t* colVal = (uint32_t*)mDataSnapshot->GetData(); + + uint32_t expected = RGBAPixelFromColor(aColor); + + for (int y = 0; y < DT_HEIGHT; y++) { + for (int x = 0; x < DT_WIDTH; x++) { + if (colVal[y * (mDataSnapshot->Stride() / 4) + x] != expected) { + LogMessage("VerifyAllPixels Failed\n"); + mTestFailed = true; + return; + } + } + } +} + +void TestDrawTargetBase::VerifyPixel(const IntPoint& aPoint, + mozilla::gfx::DeviceColor& aColor) { + uint32_t* colVal = (uint32_t*)mDataSnapshot->GetData(); + + uint32_t expected = RGBAPixelFromColor(aColor); + uint32_t rawActual = + colVal[aPoint.y * (mDataSnapshot->Stride() / 4) + aPoint.x]; + + if (rawActual != expected) { + stringstream message; + uint32_t actb = rawActual & 0xFF; + uint32_t actg = (rawActual & 0xFF00) >> 8; + uint32_t actr = (rawActual & 0xFF0000) >> 16; + uint32_t acta = (rawActual & 0xFF000000) >> 24; + uint32_t expb = expected & 0xFF; + uint32_t expg = (expected & 0xFF00) >> 8; + uint32_t expr = (expected & 0xFF0000) >> 16; + uint32_t expa = (expected & 0xFF000000) >> 24; + + message << "Verify Pixel (" << aPoint.x << "x" << aPoint.y + << ") Failed." + " Expected (" + << expr << "," << expg << "," << expb << "," << expa + << ") " + " Got (" + << actr << "," << actg << "," << actb << "," << acta << ")\n"; + + LogMessage(message.str()); + mTestFailed = true; + return; + } +} + +uint32_t TestDrawTargetBase::RGBAPixelFromColor(const DeviceColor& aColor) { + return uint8_t((aColor.b * 255) + 0.5f) | + uint8_t((aColor.g * 255) + 0.5f) << 8 | + uint8_t((aColor.r * 255) + 0.5f) << 16 | + uint8_t((aColor.a * 255) + 0.5f) << 24; +} diff --git a/gfx/2d/unittest/TestDrawTargetBase.h b/gfx/2d/unittest/TestDrawTargetBase.h new file mode 100644 index 0000000000..3f13a63106 --- /dev/null +++ b/gfx/2d/unittest/TestDrawTargetBase.h @@ -0,0 +1,38 @@ +/* -*- 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/. */ + +#pragma once + +#include "2D.h" +#include "TestBase.h" + +#define DT_WIDTH 500 +#define DT_HEIGHT 500 + +/* This general DrawTarget test class can be reimplemented by a child class + * with optional additional drawtarget-specific tests. And is intended to run + * on a 500x500 32 BPP drawtarget. + */ +class TestDrawTargetBase : public TestBase { + public: + void Initialized(); + void FillCompletely(); + void FillRect(); + + protected: + TestDrawTargetBase(); + + void RefreshSnapshot(); + + void VerifyAllPixels(const mozilla::gfx::DeviceColor& aColor); + void VerifyPixel(const mozilla::gfx::IntPoint& aPoint, + mozilla::gfx::DeviceColor& aColor); + + uint32_t RGBAPixelFromColor(const mozilla::gfx::DeviceColor& aColor); + + RefPtr<mozilla::gfx::DrawTarget> mDT; + RefPtr<mozilla::gfx::DataSourceSurface> mDataSnapshot; +}; diff --git a/gfx/2d/unittest/TestDrawTargetD2D.cpp b/gfx/2d/unittest/TestDrawTargetD2D.cpp new file mode 100644 index 0000000000..cba63129fd --- /dev/null +++ b/gfx/2d/unittest/TestDrawTargetD2D.cpp @@ -0,0 +1,22 @@ +/* -*- 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 "TestDrawTargetD2D.h" + +using namespace mozilla::gfx; +TestDrawTargetD2D::TestDrawTargetD2D() { + ::D3D10CreateDevice1( + nullptr, D3D10_DRIVER_TYPE_HARDWARE, nullptr, + D3D10_CREATE_DEVICE_BGRA_SUPPORT | + D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS, + D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, getter_AddRefs(mDevice)); + + Factory::SetDirect3D10Device(mDevice); + + mDT = Factory::CreateDrawTarget(BackendType::DIRECT2D, + IntSize(DT_WIDTH, DT_HEIGHT), + SurfaceFormat::B8G8R8A8); +} diff --git a/gfx/2d/unittest/TestDrawTargetD2D.h b/gfx/2d/unittest/TestDrawTargetD2D.h new file mode 100644 index 0000000000..f4c88336a4 --- /dev/null +++ b/gfx/2d/unittest/TestDrawTargetD2D.h @@ -0,0 +1,19 @@ +/* -*- 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/. */ + +#pragma once + +#include "TestDrawTargetBase.h" + +#include <d3d10_1.h> + +class TestDrawTargetD2D : public TestDrawTargetBase { + public: + TestDrawTargetD2D(); + + private: + RefPtr<ID3D10Device1> mDevice; +}; diff --git a/gfx/2d/unittest/TestPoint.cpp b/gfx/2d/unittest/TestPoint.cpp new file mode 100644 index 0000000000..7784c1a2a9 --- /dev/null +++ b/gfx/2d/unittest/TestPoint.cpp @@ -0,0 +1,42 @@ +/* -*- 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 "TestPoint.h" + +#include "Point.h" + +using namespace mozilla::gfx; + +TestPoint::TestPoint() { + REGISTER_TEST(TestPoint, Addition); + REGISTER_TEST(TestPoint, Subtraction); +} + +void TestPoint::Addition() { + Point a, b; + a.x = 2; + a.y = 2; + b.x = 5; + b.y = -5; + + a += b; + + VERIFY(a.x == 7.f); + VERIFY(a.y == -3.f); +} + +void TestPoint::Subtraction() { + Point a, b; + a.x = 2; + a.y = 2; + b.x = 5; + b.y = -5; + + a -= b; + + VERIFY(a.x == -3.f); + VERIFY(a.y == 7.f); +} diff --git a/gfx/2d/unittest/TestPoint.h b/gfx/2d/unittest/TestPoint.h new file mode 100644 index 0000000000..2a0c5e945f --- /dev/null +++ b/gfx/2d/unittest/TestPoint.h @@ -0,0 +1,17 @@ +/* -*- 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/. */ + +#pragma once + +#include "TestBase.h" + +class TestPoint : public TestBase { + public: + TestPoint(); + + void Addition(); + void Subtraction(); +}; diff --git a/gfx/2d/unittest/TestScaling.cpp b/gfx/2d/unittest/TestScaling.cpp new file mode 100644 index 0000000000..fd15455f26 --- /dev/null +++ b/gfx/2d/unittest/TestScaling.cpp @@ -0,0 +1,235 @@ +/* -*- 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 "TestScaling.h" + +#include "ImageScaling.h" + +using namespace mozilla::gfx; + +TestScaling::TestScaling() { + REGISTER_TEST(TestScaling, BasicHalfScale); + REGISTER_TEST(TestScaling, DoubleHalfScale); + REGISTER_TEST(TestScaling, UnevenHalfScale); + REGISTER_TEST(TestScaling, OddStrideHalfScale); + REGISTER_TEST(TestScaling, VerticalHalfScale); + REGISTER_TEST(TestScaling, HorizontalHalfScale); + REGISTER_TEST(TestScaling, MixedHalfScale); +} + +void TestScaling::BasicHalfScale() { + std::vector<uint8_t> data; + data.resize(500 * 500 * 4); + + uint32_t* pixels = reinterpret_cast<uint32_t*>(&data.front()); + for (int y = 0; y < 500; y += 2) { + for (int x = 0; x < 500; x += 2) { + pixels[y * 500 + x] = 0xff00ff00; + pixels[y * 500 + x + 1] = 0xff00ffff; + pixels[(y + 1) * 500 + x] = 0xff000000; + pixels[(y + 1) * 500 + x + 1] = 0xff0000ff; + } + } + ImageHalfScaler scaler(&data.front(), 500 * 4, IntSize(500, 500)); + + scaler.ScaleForSize(IntSize(220, 240)); + + VERIFY(scaler.GetSize().width == 250); + VERIFY(scaler.GetSize().height == 250); + + pixels = (uint32_t*)scaler.GetScaledData(); + + for (int y = 0; y < 250; y++) { + for (int x = 0; x < 250; x++) { + VERIFY(pixels[y * (scaler.GetStride() / 4) + x] == 0xff007f7f); + } + } +} + +void TestScaling::DoubleHalfScale() { + std::vector<uint8_t> data; + data.resize(500 * 500 * 4); + + uint32_t* pixels = reinterpret_cast<uint32_t*>(&data.front()); + for (int y = 0; y < 500; y += 2) { + for (int x = 0; x < 500; x += 2) { + pixels[y * 500 + x] = 0xff00ff00; + pixels[y * 500 + x + 1] = 0xff00ffff; + pixels[(y + 1) * 500 + x] = 0xff000000; + pixels[(y + 1) * 500 + x + 1] = 0xff0000ff; + } + } + ImageHalfScaler scaler(&data.front(), 500 * 4, IntSize(500, 500)); + + scaler.ScaleForSize(IntSize(120, 110)); + VERIFY(scaler.GetSize().width == 125); + VERIFY(scaler.GetSize().height == 125); + + pixels = (uint32_t*)scaler.GetScaledData(); + + for (int y = 0; y < 125; y++) { + for (int x = 0; x < 125; x++) { + VERIFY(pixels[y * (scaler.GetStride() / 4) + x] == 0xff007f7f); + } + } +} + +void TestScaling::UnevenHalfScale() { + std::vector<uint8_t> data; + // Use a 16-byte aligned stride still, we test none-aligned strides + // separately. + data.resize(499 * 500 * 4); + + uint32_t* pixels = reinterpret_cast<uint32_t*>(&data.front()); + for (int y = 0; y < 500; y += 2) { + for (int x = 0; x < 500; x += 2) { + pixels[y * 500 + x] = 0xff00ff00; + if (x < 498) { + pixels[y * 500 + x + 1] = 0xff00ffff; + } + if (y < 498) { + pixels[(y + 1) * 500 + x] = 0xff000000; + if (x < 498) { + pixels[(y + 1) * 500 + x + 1] = 0xff0000ff; + } + } + } + } + ImageHalfScaler scaler(&data.front(), 500 * 4, IntSize(499, 499)); + + scaler.ScaleForSize(IntSize(220, 220)); + VERIFY(scaler.GetSize().width == 249); + VERIFY(scaler.GetSize().height == 249); + + pixels = (uint32_t*)scaler.GetScaledData(); + + for (int y = 0; y < 249; y++) { + for (int x = 0; x < 249; x++) { + VERIFY(pixels[y * (scaler.GetStride() / 4) + x] == 0xff007f7f); + } + } +} + +void TestScaling::OddStrideHalfScale() { + std::vector<uint8_t> data; + // Use a 4-byte aligned stride to test if that doesn't cause any issues. + data.resize(499 * 499 * 4); + + uint32_t* pixels = reinterpret_cast<uint32_t*>(&data.front()); + for (int y = 0; y < 500; y += 2) { + for (int x = 0; x < 500; x += 2) { + pixels[y * 499 + x] = 0xff00ff00; + if (x < 498) { + pixels[y * 499 + x + 1] = 0xff00ffff; + } + if (y < 498) { + pixels[(y + 1) * 499 + x] = 0xff000000; + if (x < 498) { + pixels[(y + 1) * 499 + x + 1] = 0xff0000ff; + } + } + } + } + ImageHalfScaler scaler(&data.front(), 499 * 4, IntSize(499, 499)); + + scaler.ScaleForSize(IntSize(220, 220)); + VERIFY(scaler.GetSize().width == 249); + VERIFY(scaler.GetSize().height == 249); + + pixels = (uint32_t*)scaler.GetScaledData(); + + for (int y = 0; y < 249; y++) { + for (int x = 0; x < 249; x++) { + VERIFY(pixels[y * (scaler.GetStride() / 4) + x] == 0xff007f7f); + } + } +} +void TestScaling::VerticalHalfScale() { + std::vector<uint8_t> data; + data.resize(500 * 500 * 4); + + uint32_t* pixels = reinterpret_cast<uint32_t*>(&data.front()); + for (int y = 0; y < 500; y += 2) { + for (int x = 0; x < 500; x += 2) { + pixels[y * 500 + x] = 0xff00ff00; + pixels[y * 500 + x + 1] = 0xff00ffff; + pixels[(y + 1) * 500 + x] = 0xff000000; + pixels[(y + 1) * 500 + x + 1] = 0xff0000ff; + } + } + ImageHalfScaler scaler(&data.front(), 500 * 4, IntSize(500, 500)); + + scaler.ScaleForSize(IntSize(400, 240)); + VERIFY(scaler.GetSize().width == 500); + VERIFY(scaler.GetSize().height == 250); + + pixels = (uint32_t*)scaler.GetScaledData(); + + for (int y = 0; y < 250; y++) { + for (int x = 0; x < 500; x += 2) { + VERIFY(pixels[y * (scaler.GetStride() / 4) + x] == 0xff007f00); + VERIFY(pixels[y * (scaler.GetStride() / 4) + x + 1] == 0xff007fff); + } + } +} + +void TestScaling::HorizontalHalfScale() { + std::vector<uint8_t> data; + data.resize(520 * 500 * 4); + + uint32_t* pixels = reinterpret_cast<uint32_t*>(&data.front()); + for (int y = 0; y < 500; y++) { + for (int x = 0; x < 520; x += 8) { + pixels[y * 520 + x] = 0xff00ff00; + pixels[y * 520 + x + 1] = 0xff00ffff; + pixels[y * 520 + x + 2] = 0xff000000; + pixels[y * 520 + x + 3] = 0xff0000ff; + pixels[y * 520 + x + 4] = 0xffff00ff; + pixels[y * 520 + x + 5] = 0xff0000ff; + pixels[y * 520 + x + 6] = 0xffffffff; + pixels[y * 520 + x + 7] = 0xff0000ff; + } + } + ImageHalfScaler scaler(&data.front(), 520 * 4, IntSize(520, 500)); + + scaler.ScaleForSize(IntSize(240, 400)); + VERIFY(scaler.GetSize().width == 260); + VERIFY(scaler.GetSize().height == 500); + + pixels = (uint32_t*)scaler.GetScaledData(); + + for (int y = 0; y < 500; y++) { + for (int x = 0; x < 260; x += 4) { + VERIFY(pixels[y * (scaler.GetStride() / 4) + x] == 0xff00ff7f); + VERIFY(pixels[y * (scaler.GetStride() / 4) + x + 1] == 0xff00007f); + VERIFY(pixels[y * (scaler.GetStride() / 4) + x + 2] == 0xff7f00ff); + VERIFY(pixels[y * (scaler.GetStride() / 4) + x + 3] == 0xff7f7fff); + } + } +} + +void TestScaling::MixedHalfScale() { + std::vector<uint8_t> data; + data.resize(500 * 500 * 4); + + uint32_t* pixels = reinterpret_cast<uint32_t*>(&data.front()); + for (int y = 0; y < 500; y += 2) { + for (int x = 0; x < 500; x += 2) { + pixels[y * 500 + x] = 0xff00ff00; + pixels[y * 500 + x + 1] = 0xff00ffff; + pixels[(y + 1) * 500 + x] = 0xff000000; + pixels[(y + 1) * 500 + x + 1] = 0xff0000ff; + } + } + ImageHalfScaler scaler(&data.front(), 500 * 4, IntSize(500, 500)); + + scaler.ScaleForSize(IntSize(120, 240)); + VERIFY(scaler.GetSize().width == 125); + VERIFY(scaler.GetSize().height == 250); + scaler.ScaleForSize(IntSize(240, 120)); + VERIFY(scaler.GetSize().width == 250); + VERIFY(scaler.GetSize().height == 125); +} diff --git a/gfx/2d/unittest/TestScaling.h b/gfx/2d/unittest/TestScaling.h new file mode 100644 index 0000000000..dbbcda91fa --- /dev/null +++ b/gfx/2d/unittest/TestScaling.h @@ -0,0 +1,22 @@ +/* -*- 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/. */ + +#pragma once + +#include "TestBase.h" + +class TestScaling : public TestBase { + public: + TestScaling(); + + void BasicHalfScale(); + void DoubleHalfScale(); + void UnevenHalfScale(); + void OddStrideHalfScale(); + void VerticalHalfScale(); + void HorizontalHalfScale(); + void MixedHalfScale(); +}; diff --git a/gfx/2d/unittest/unittest.vcxproj b/gfx/2d/unittest/unittest.vcxproj new file mode 100644 index 0000000000..7ddf925303 --- /dev/null +++ b/gfx/2d/unittest/unittest.vcxproj @@ -0,0 +1,94 @@ +<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{CCF4BC8B-0CED-47CA-B621-ABF1832527D9}</ProjectGuid>
+ <RootNamespace>unittest</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LibraryPath>$(DXSDK_DIR)\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib</LibraryPath>
+ <IncludePath>$(ProjectDir)..\;$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LibraryPath>$(DXSDK_DIR)\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib</LibraryPath>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>../$(Configuration)/gfx2d.lib;dxguid.lib;d3d10_1.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>../</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalDependencies>../$(Configuration)/gfx2d.lib;dxguid.lib;d3d10_1.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="Main.cpp" />
+ <ClCompile Include="SanityChecks.cpp" />
+ <ClCompile Include="TestBase.cpp" />
+ <ClCompile Include="TestDrawTargetBase.cpp" />
+ <ClCompile Include="TestDrawTargetD2D.cpp" />
+ <ClCompile Include="TestPoint.cpp" />
+ <ClCompile Include="TestScaling.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="TestDrawTargetBase.h" />
+ <ClInclude Include="SanityChecks.h" />
+ <ClInclude Include="TestBase.h" />
+ <ClInclude Include="TestDrawTargetD2D.h" />
+ <ClInclude Include="TestPoint.h" />
+ <ClInclude Include="TestScaling.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file |