tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestTextures.cpp (9487B)


      1 /* vim:set ts=2 sw=2 sts=2 et: */
      2 /* Any copyright is dedicated to the Public Domain.
      3 * http://creativecommons.org/publicdomain/zero/1.0/
      4 */
      5 
      6 #include "gtest/gtest.h"
      7 #include "gmock/gmock.h"
      8 
      9 #include "mozilla/gfx/2D.h"
     10 #include "mozilla/gfx/Tools.h"
     11 #include "mozilla/layers/BufferTexture.h"
     12 #include "mozilla/layers/ImageBridgeChild.h"  // for ImageBridgeChild
     13 #include "mozilla/layers/TextureClient.h"
     14 #include "mozilla/layers/TextureHost.h"
     15 #include "mozilla/RefPtr.h"
     16 #include "gfx2DGlue.h"
     17 #include "gfxImageSurface.h"
     18 #include "gfxPlatform.h"
     19 #include "gfxTypes.h"
     20 #include "ImageContainer.h"
     21 #include "mozilla/layers/ImageDataSerializer.h"
     22 
     23 using namespace mozilla;
     24 using namespace mozilla::gfx;
     25 using namespace mozilla::layers;
     26 
     27 /*
     28 * This test performs the following actions:
     29 * - creates a surface
     30 * - initialize a texture client with it
     31 * - serilaizes the texture client
     32 * - deserializes the data into a texture host
     33 * - reads the surface from the texture host.
     34 *
     35 * The surface in the end should be equal to the inital one.
     36 * This test is run for different combinations of texture types and
     37 * image formats.
     38 */
     39 
     40 namespace mozilla {
     41 namespace layers {
     42 
     43 class TestSurfaceAllocator final : public ISurfaceAllocator {
     44 public:
     45  TestSurfaceAllocator() = default;
     46  virtual ~TestSurfaceAllocator() = default;
     47 
     48  bool IsSameProcess() const override { return true; }
     49 };
     50 
     51 // fills the surface with values betwee 0 and 100.
     52 static void SetupSurface(gfxImageSurface* surface) {
     53  int bpp = gfxASurface::BytePerPixelFromFormat(surface->Format());
     54  int stride = surface->Stride();
     55  uint8_t val = 0;
     56  uint8_t* data = surface->Data();
     57  for (int y = 0; y < surface->Height(); ++y) {
     58    for (int x = 0; x < surface->Height(); ++x) {
     59      for (int b = 0; b < bpp; ++b) {
     60        data[y * stride + x * bpp + b] = val;
     61        if (val == 100) {
     62          val = 0;
     63        } else {
     64          ++val;
     65        }
     66      }
     67    }
     68  }
     69 }
     70 
     71 // return true if two surfaces contain the same data
     72 static void AssertSurfacesEqual(gfxImageSurface* surface1,
     73                                gfxImageSurface* surface2) {
     74  ASSERT_EQ(surface1->GetSize(), surface2->GetSize());
     75  ASSERT_EQ(surface1->Format(), surface2->Format());
     76 
     77  uint8_t* data1 = surface1->Data();
     78  uint8_t* data2 = surface2->Data();
     79  int stride1 = surface1->Stride();
     80  int stride2 = surface2->Stride();
     81  int bpp = gfxASurface::BytePerPixelFromFormat(surface1->Format());
     82 
     83  for (int y = 0; y < surface1->Height(); ++y) {
     84    for (int x = 0; x < surface1->Width(); ++x) {
     85      for (int b = 0; b < bpp; ++b) {
     86        ASSERT_EQ(data1[y * stride1 + x * bpp + b],
     87                  data2[y * stride2 + x * bpp + b]);
     88      }
     89    }
     90  }
     91 }
     92 
     93 static void AssertSurfacesEqual(SourceSurface* surface1,
     94                                SourceSurface* surface2) {
     95  ASSERT_EQ(surface1->GetSize(), surface2->GetSize());
     96  ASSERT_EQ(surface1->GetFormat(), surface2->GetFormat());
     97 
     98  RefPtr<DataSourceSurface> dataSurface1 = surface1->GetDataSurface();
     99  RefPtr<DataSourceSurface> dataSurface2 = surface2->GetDataSurface();
    100  DataSourceSurface::MappedSurface map1;
    101  DataSourceSurface::MappedSurface map2;
    102  if (!dataSurface1->Map(DataSourceSurface::READ, &map1)) {
    103    return;
    104  }
    105  if (!dataSurface2->Map(DataSourceSurface::READ, &map2)) {
    106    dataSurface1->Unmap();
    107    return;
    108  }
    109  uint8_t* data1 = map1.mData;
    110  uint8_t* data2 = map2.mData;
    111  int stride1 = map1.mStride;
    112  int stride2 = map2.mStride;
    113  int bpp = BytesPerPixel(surface1->GetFormat());
    114  int width = surface1->GetSize().width;
    115  int height = surface1->GetSize().height;
    116 
    117  for (int y = 0; y < height; ++y) {
    118    for (int x = 0; x < width; ++x) {
    119      for (int b = 0; b < bpp; ++b) {
    120        ASSERT_EQ(data1[y * stride1 + x * bpp + b],
    121                  data2[y * stride2 + x * bpp + b]);
    122      }
    123    }
    124  }
    125 
    126  dataSurface1->Unmap();
    127  dataSurface2->Unmap();
    128 }
    129 
    130 // Run the test for a texture client and a surface
    131 void TestTextureClientSurface(TextureClient* texture,
    132                              gfxImageSurface* surface) {
    133  // client allocation
    134  ASSERT_TRUE(texture->CanExposeDrawTarget());
    135 
    136  ASSERT_TRUE(texture->Lock(OpenMode::OPEN_READ_WRITE));
    137  // client painting
    138  RefPtr<DrawTarget> dt = texture->BorrowDrawTarget();
    139  RefPtr<SourceSurface> source =
    140      gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt, surface);
    141  dt->CopySurface(source, IntRect(IntPoint(), source->GetSize()), IntPoint());
    142 
    143  RefPtr<SourceSurface> snapshot = dt->Snapshot();
    144 
    145  AssertSurfacesEqual(snapshot, source);
    146 
    147  dt = nullptr;  // drop reference before calling Unlock()
    148  texture->Unlock();
    149 
    150  // client serialization
    151  SurfaceDescriptor descriptor;
    152  ASSERT_TRUE(texture->ToSurfaceDescriptor(descriptor));
    153 
    154  ASSERT_NE(descriptor.type(), SurfaceDescriptor::Tnull_t);
    155 
    156  // host deserialization
    157  RefPtr<TestSurfaceAllocator> deallocator = new TestSurfaceAllocator();
    158  RefPtr<TextureHost> host = CreateBackendIndependentTextureHost(
    159      descriptor, deallocator, LayersBackend::LAYERS_NONE, texture->GetFlags());
    160 
    161  ASSERT_TRUE(host.get() != nullptr);
    162  ASSERT_EQ(host->GetFlags(), texture->GetFlags());
    163 }
    164 
    165 // Same as above, for YCbCr surfaces
    166 void TestTextureClientYCbCr(TextureClient* client, PlanarYCbCrData& ycbcrData) {
    167  client->Lock(OpenMode::OPEN_READ_WRITE);
    168  UpdateYCbCrTextureClient(client, ycbcrData);
    169  client->Unlock();
    170 
    171  // client serialization
    172  SurfaceDescriptor descriptor;
    173  ASSERT_TRUE(client->ToSurfaceDescriptor(descriptor));
    174 
    175  ASSERT_EQ(descriptor.type(), SurfaceDescriptor::TSurfaceDescriptorBuffer);
    176  auto bufferDesc = descriptor.get_SurfaceDescriptorBuffer();
    177  ASSERT_EQ(bufferDesc.desc().type(), BufferDescriptor::TYCbCrDescriptor);
    178  auto ycbcrDesc = bufferDesc.desc().get_YCbCrDescriptor();
    179  ASSERT_EQ(ycbcrDesc.ySize(), ycbcrData.YDataSize());
    180  ASSERT_EQ(ycbcrDesc.cbCrSize(), ycbcrData.CbCrDataSize());
    181  ASSERT_EQ(ycbcrDesc.stereoMode(), ycbcrData.mStereoMode);
    182 
    183  // host deserialization
    184  RefPtr<TestSurfaceAllocator> deallocator = new TestSurfaceAllocator();
    185  RefPtr<TextureHost> textureHost = CreateBackendIndependentTextureHost(
    186      descriptor, deallocator, LayersBackend::LAYERS_NONE, client->GetFlags());
    187 
    188  RefPtr<BufferTextureHost> host =
    189      static_cast<BufferTextureHost*>(textureHost.get());
    190 
    191  ASSERT_TRUE(host.get() != nullptr);
    192  ASSERT_EQ(host->GetFlags(), client->GetFlags());
    193 }
    194 
    195 }  // namespace layers
    196 }  // namespace mozilla
    197 
    198 TEST(Layers, TextureSerialization)
    199 {
    200  // the test is run on all the following image formats
    201  gfxImageFormat formats[3] = {
    202      SurfaceFormat::A8R8G8B8_UINT32,
    203      SurfaceFormat::X8R8G8B8_UINT32,
    204      SurfaceFormat::A8,
    205  };
    206 
    207  for (int f = 0; f < 3; ++f) {
    208    RefPtr<gfxImageSurface> surface =
    209        new gfxImageSurface(IntSize(400, 300), formats[f]);
    210    SetupSurface(surface.get());
    211    AssertSurfacesEqual(surface, surface);
    212 
    213    auto texData = BufferTextureData::Create(
    214        surface->GetSize(), gfx::ImageFormatToSurfaceFormat(surface->Format()),
    215        gfx::BackendType::CAIRO, LayersBackend::LAYERS_NONE,
    216        TextureFlags::DEALLOCATE_CLIENT, ALLOC_DEFAULT, nullptr);
    217    ASSERT_TRUE(!!texData);
    218 
    219    RefPtr<TextureClient> client =
    220        new TextureClient(texData, TextureFlags::DEALLOCATE_CLIENT, nullptr);
    221 
    222    TestTextureClientSurface(client, surface);
    223 
    224    // XXX - Test more texture client types.
    225  }
    226 }
    227 
    228 TEST(Layers, TextureYCbCrSerialization)
    229 {
    230  RefPtr<gfxImageSurface> ySurface =
    231      new gfxImageSurface(IntSize(400, 300), SurfaceFormat::A8);
    232  RefPtr<gfxImageSurface> cbSurface =
    233      new gfxImageSurface(IntSize(200, 150), SurfaceFormat::A8);
    234  RefPtr<gfxImageSurface> crSurface =
    235      new gfxImageSurface(IntSize(200, 150), SurfaceFormat::A8);
    236  SetupSurface(ySurface.get());
    237  SetupSurface(cbSurface.get());
    238  SetupSurface(crSurface.get());
    239 
    240  PlanarYCbCrData clientData;
    241  clientData.mYChannel = ySurface->Data();
    242  clientData.mCbChannel = cbSurface->Data();
    243  clientData.mCrChannel = crSurface->Data();
    244  clientData.mPictureRect = IntRect(IntPoint(0, 0), ySurface->GetSize());
    245  clientData.mYStride = ySurface->Stride();
    246  clientData.mCbCrStride = cbSurface->Stride();
    247  clientData.mStereoMode = StereoMode::MONO;
    248  clientData.mYUVColorSpace = YUVColorSpace::BT601;
    249  clientData.mColorDepth = ColorDepth::COLOR_8;
    250  clientData.mChromaSubsampling = ChromaSubsampling::HALF_WIDTH_AND_HEIGHT;
    251  clientData.mYSkip = 0;
    252  clientData.mCbSkip = 0;
    253  clientData.mCrSkip = 0;
    254  clientData.mCrSkip = 0;
    255 
    256  uint32_t namespaceId = 1;
    257  ImageBridgeChild::InitSameProcess(namespaceId);
    258 
    259  RefPtr<ImageBridgeChild> imageBridge = ImageBridgeChild::GetSingleton();
    260  static int retry = 5;
    261  while (!imageBridge->IPCOpen() && retry) {
    262    // IPDL connection takes time especially in slow testing environment, like
    263    // VM machines. Here we added retry mechanism to wait for IPDL connnection.
    264 #ifdef XP_WIN
    265    Sleep(1);
    266 #else
    267    sleep(1);
    268 #endif
    269    retry--;
    270  }
    271 
    272  // Skip this testing if IPDL connection is not ready
    273  if (!retry && !imageBridge->IPCOpen()) {
    274    return;
    275  }
    276 
    277  RefPtr<TextureClient> client = TextureClient::CreateForYCbCr(
    278      imageBridge, clientData.mPictureRect, clientData.YDataSize(),
    279      clientData.mYStride, clientData.CbCrDataSize(), clientData.mCbCrStride,
    280      StereoMode::MONO, ColorDepth::COLOR_8, YUVColorSpace::BT601,
    281      ColorRange::LIMITED, clientData.mChromaSubsampling,
    282      TextureFlags::DEALLOCATE_CLIENT);
    283 
    284  TestTextureClientYCbCr(client, clientData);
    285 
    286  // XXX - Test more texture client types.
    287 }