/* vim:set ts=2 sw=2 sts=2 et: */ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ #include "gfxUtils.h" #include "gtest/gtest.h" #include "TestLayers.h" #include "mozilla/gfx/2D.h" #include "mozilla/RefPtr.h" #include "mozilla/layers/BasicCompositor.h" // for BasicCompositor #include "mozilla/layers/Compositor.h" // for Compositor #include "mozilla/layers/CompositorOGL.h" // for CompositorOGL #include "mozilla/layers/CompositorTypes.h" #include "mozilla/layers/LayerManagerComposite.h" #include "MockWidget.h" #include "nsBaseWidget.h" #include const int gCompWidth = 256; const int gCompHeight = 256; using namespace mozilla; using namespace mozilla::gfx; using namespace mozilla::layers; using namespace mozilla::gl; struct LayerManagerData { RefPtr mWidget; RefPtr mCompositor; RefPtr mCompositorWidget; RefPtr mLayerManager; LayerManagerData(Compositor* compositor, MockWidget* widget, widget::CompositorWidget* aWidget, LayerManagerComposite* layerManager) : mWidget(widget), mCompositor(compositor), mCompositorWidget(aWidget), mLayerManager(layerManager) {} }; static already_AddRefed CreateTestCompositor( LayersBackend backend, widget::CompositorWidget* widget) { gfxPlatform::GetPlatform(); RefPtr compositor; if (backend == LayersBackend::LAYERS_OPENGL) { compositor = new CompositorOGL(nullptr, widget, gCompWidth, gCompHeight, true); compositor->SetDestinationSurfaceSize(IntSize(gCompWidth, gCompHeight)); } else if (backend == LayersBackend::LAYERS_BASIC) { compositor = new BasicCompositor(nullptr, widget); #ifdef XP_WIN } else if (backend == LayersBackend::LAYERS_D3D11) { // compositor = new CompositorD3D11(); MOZ_CRASH(); // No support yet #endif } nsCString failureReason; if (!compositor || !compositor->Initialize(&failureReason)) { printf_stderr( "Failed to construct layer manager for the requested backend\n"); abort(); } return compositor.forget(); } /** * Get a list of layers managers for the platform to run the test on. */ static std::vector GetLayerManagers( std::vector aBackends) { std::vector managers; for (size_t i = 0; i < aBackends.size(); i++) { auto backend = aBackends[i]; RefPtr widget = new MockWidget(gCompWidth, gCompHeight); CompositorOptions options; RefPtr proxy = new widget::InProcessCompositorWidget(options, widget); RefPtr compositor = CreateTestCompositor(backend, proxy); RefPtr layerManager = new LayerManagerComposite(compositor); managers.push_back( LayerManagerData(compositor, widget, proxy, layerManager)); } return managers; } /** * This will return the default list of backends that * units test should run against. */ static std::vector GetPlatformBackends() { std::vector backends; // For now we only support Basic for gtest backends.push_back(LayersBackend::LAYERS_BASIC); #ifdef XP_MACOSX backends.push_back(LayersBackend::LAYERS_OPENGL); #endif // TODO Support OGL/D3D backends with unit test return backends; } static already_AddRefed CreateDT() { return gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget( IntSize(gCompWidth, gCompHeight), SurfaceFormat::B8G8R8A8); } static bool CompositeAndCompare(RefPtr layerManager, DrawTarget* refDT) { RefPtr drawTarget = CreateDT(); layerManager->BeginTransactionWithDrawTarget( drawTarget, IntRect(0, 0, gCompWidth, gCompHeight)); layerManager->EndTransaction(TimeStamp::Now()); RefPtr ss = drawTarget->Snapshot(); RefPtr dss = ss->GetDataSurface(); DataSourceSurface::ScopedMap dssMap(dss, DataSourceSurface::READ); uint8_t* bitmap = dssMap.GetData(); RefPtr ssRef = refDT->Snapshot(); RefPtr dssRef = ssRef->GetDataSurface(); DataSourceSurface::ScopedMap dssRefMap(dssRef, DataSourceSurface::READ); uint8_t* bitmapRef = dssRefMap.GetData(); for (int y = 0; y < gCompHeight; y++) { for (int x = 0; x < gCompWidth; x++) { for (size_t channel = 0; channel < 4; channel++) { uint8_t bit = bitmap[y * dssMap.GetStride() + x * 4 + channel]; uint8_t bitRef = bitmapRef[y * dssRefMap.GetStride() + x * 4 + channel]; if (bit != bitRef) { printf("Layer Tree:\n"); layerManager->Dump(); printf("Original:\n"); gfxUtils::DumpAsDataURI(drawTarget); printf("\n\n"); printf("Reference:\n"); gfxUtils::DumpAsDataURI(refDT); printf("\n\n"); return false; } } } } return true; } TEST(Gfx, CompositorConstruct) { auto layerManagers = GetLayerManagers(GetPlatformBackends()); } TEST(Gfx, CompositorSimpleTree) { auto layerManagers = GetLayerManagers(GetPlatformBackends()); for (size_t i = 0; i < layerManagers.size(); i++) { RefPtr layerManager = layerManagers[i].mLayerManager; RefPtr lmBase = layerManager.get(); nsTArray> layers; nsIntRegion layerVisibleRegion[] = { nsIntRegion(IntRect(0, 0, gCompWidth, gCompHeight)), nsIntRegion(IntRect(0, 0, gCompWidth, gCompHeight)), nsIntRegion(IntRect(0, 0, 100, 100)), nsIntRegion(IntRect(0, 50, 100, 100)), }; RefPtr root = CreateLayerTree("c(ooo)", layerVisibleRegion, nullptr, lmBase, layers); { // background ColorLayer* colorLayer = layers[1]->AsColorLayer(); colorLayer->SetColor(DeviceColor(1.f, 0.f, 1.f, 1.f)); colorLayer->SetBounds( colorLayer->GetVisibleRegion().GetBounds().ToUnknownRect()); } { ColorLayer* colorLayer = layers[2]->AsColorLayer(); colorLayer->SetColor(DeviceColor(1.f, 0.f, 0.f, 1.f)); colorLayer->SetBounds( colorLayer->GetVisibleRegion().GetBounds().ToUnknownRect()); } { ColorLayer* colorLayer = layers[3]->AsColorLayer(); colorLayer->SetColor(DeviceColor(0.f, 0.f, 1.f, 1.f)); colorLayer->SetBounds( colorLayer->GetVisibleRegion().GetBounds().ToUnknownRect()); } RefPtr refDT = CreateDT(); refDT->FillRect(Rect(0, 0, gCompWidth, gCompHeight), ColorPattern(DeviceColor(1.f, 0.f, 1.f, 1.f))); refDT->FillRect(Rect(0, 0, 100, 100), ColorPattern(DeviceColor(1.f, 0.f, 0.f, 1.f))); refDT->FillRect(Rect(0, 50, 100, 100), ColorPattern(DeviceColor(0.f, 0.f, 1.f, 1.f))); EXPECT_TRUE(CompositeAndCompare(layerManager, refDT)); } }