/* 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/. */ // Tests for MacIOSurfaceHelpers: verifies that CPU readback of MacIOSurfaces // via CreateSourceSurfaceFromMacIOSurface produces correct BGRA pixel values // for 8-bit and 10-bit biplanar formats (NV12, NV16, P010, P210). #include "MacIOSurfaceHelpers.h" #include "gtest/gtest.h" #include "mozilla/gfx/2D.h" #include "mozilla/gfx/MacIOSurface.h" using namespace mozilla; using namespace mozilla::gfx; using namespace mozilla::layers; template static void FillBiPlanarSurface(MacIOSurface* aSurface, T aYVal, T aCbCrVal) { T* yPlane = reinterpret_cast(aSurface->GetBaseAddressOfPlane(0)); size_t yStride = aSurface->GetBytesPerRow(0) / sizeof(T); for (size_t y = 0; y < aSurface->GetDevicePixelHeight(0); y++) { for (size_t x = 0; x < aSurface->GetDevicePixelWidth(0); x++) { yPlane[y * yStride + x] = aYVal; } } T* cbcrPlane = reinterpret_cast(aSurface->GetBaseAddressOfPlane(1)); size_t cbcrStride = aSurface->GetBytesPerRow(1) / sizeof(T); for (size_t y = 0; y < aSurface->GetDevicePixelHeight(1); y++) { for (size_t x = 0; x < aSurface->GetDevicePixelWidth(1); x++) { cbcrPlane[y * cbcrStride + x * 2] = aCbCrVal; cbcrPlane[y * cbcrStride + x * 2 + 1] = aCbCrVal; } } } static void TestBiPlanarMidGrayReadback(const IntSize& aYSize, const IntSize& aCbCrSize, ChromaSubsampling aSubsampling, ColorDepth aColorDepth) { RefPtr surface = MacIOSurface::CreateBiPlanarSurface( aYSize, aCbCrSize, aSubsampling, YUVColorSpace::BT709, TransferFunction::BT709, ColorRange::FULL, aColorDepth, MacIOSurface::AllowAlpha::Yes); ASSERT_TRUE(surface); ASSERT_TRUE(surface->Lock(false)); if (aColorDepth == ColorDepth::COLOR_8) { // Mid-gray in 8-bit full range: Y=Cb=Cr=128. FillBiPlanarSurface(surface, 128, 128); } else { // Mid-gray in 10-bit full range: Y=Cb=Cr=512, stored in bits 15:6. FillBiPlanarSurface(surface, uint16_t(512) << 6, uint16_t(512) << 6); } surface->Unlock(); RefPtr sourceSurface = CreateSourceSurfaceFromMacIOSurface(surface); ASSERT_TRUE(sourceSurface); ASSERT_EQ(sourceSurface->GetSize(), aYSize); RefPtr dataSurface = sourceSurface->GetDataSurface(); ASSERT_TRUE(dataSurface); DataSourceSurface::ScopedMap map(dataSurface, DataSourceSurface::READ); ASSERT_TRUE(map.IsMapped()); uint8_t* pixels = map.GetData(); const int32_t stride = map.GetStride(); for (int y = 0; y < aYSize.height; y++) { for (int x = 0; x < aYSize.width; x++) { EXPECT_NEAR(pixels[y * stride + x * 4 + 0], 128, 3) << "Pixel (" << x << "," << y << ")"; EXPECT_NEAR(pixels[y * stride + x * 4 + 1], 128, 3) << "Pixel (" << x << "," << y << ")"; EXPECT_NEAR(pixels[y * stride + x * 4 + 2], 128, 3) << "Pixel (" << x << "," << y << ")"; } } } // Tests that an NV12 (8-bit 4:2:0 biplanar) IOSurface filled with mid-gray // produces the correct BGRA output via CreateSourceSurfaceFromMacIOSurface. TEST(MacIOSurfaceHelpers, NV12Readback) { ASSERT_NO_FATAL_FAILURE(TestBiPlanarMidGrayReadback( IntSize(16, 16), IntSize(8, 8), ChromaSubsampling::HALF_WIDTH_AND_HEIGHT, ColorDepth::COLOR_8)); } // Tests that an NV16 (8-bit 4:2:2 biplanar) IOSurface filled with mid-gray // produces the correct BGRA output via CreateSourceSurfaceFromMacIOSurface. TEST(MacIOSurfaceHelpers, NV16Readback) { ASSERT_NO_FATAL_FAILURE(TestBiPlanarMidGrayReadback( IntSize(16, 16), IntSize(8, 16), ChromaSubsampling::HALF_WIDTH, ColorDepth::COLOR_8)); } // Tests that a P010 (10-bit 4:2:0 biplanar) IOSurface filled with mid-gray // produces the correct BGRA output via CreateSourceSurfaceFromMacIOSurface. TEST(MacIOSurfaceHelpers, P010Readback) { ASSERT_NO_FATAL_FAILURE(TestBiPlanarMidGrayReadback( IntSize(16, 16), IntSize(8, 8), ChromaSubsampling::HALF_WIDTH_AND_HEIGHT, ColorDepth::COLOR_10)); } // Tests that an P210 (10-bit 4:2:2 biplanar) IOSurface filled with mid-gray // produces the correct BGRA output via CreateSourceSurfaceFromMacIOSurface. TEST(MacIOSurfaceHelpers, P210Readback) { ASSERT_NO_FATAL_FAILURE(TestBiPlanarMidGrayReadback( IntSize(16, 16), IntSize(8, 16), ChromaSubsampling::HALF_WIDTH, ColorDepth::COLOR_10)); }