tor-browser

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

CompositorBench.cpp (10859B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "CompositorBench.h"
      8 
      9 #ifdef MOZ_COMPOSITOR_BENCH
     10 #  include "mozilla/gfx/2D.h"
     11 #  include "mozilla/layers/Compositor.h"
     12 #  include "mozilla/layers/Effects.h"
     13 #  include "mozilla/ProfilerMarkers.h"
     14 #  include "mozilla/StaticPrefs_layers.h"
     15 #  include "mozilla/TimeStamp.h"
     16 #  include <math.h>
     17 
     18 #  define TEST_STEPS 1000
     19 #  define DURATION_THRESHOLD 30
     20 #  define THRESHOLD_ABORT_COUNT 5
     21 
     22 namespace mozilla {
     23 namespace layers {
     24 
     25 using namespace mozilla::gfx;
     26 
     27 static float SimplePseudoRandom(int aStep, int aCount) {
     28  srand(aStep * 1000 + aCount);
     29  return static_cast<float>(rand()) / static_cast<float>(RAND_MAX);
     30 }
     31 
     32 class BenchTest {
     33 public:
     34  BenchTest(const char* aTestName) : mTestName(aTestName) {}
     35 
     36  virtual ~BenchTest() = default;
     37 
     38  virtual void Setup(Compositor* aCompositor, size_t aStep) {}
     39  virtual void Teardown(Compositor* aCompositor) {}
     40  virtual void DrawFrame(Compositor* aCompositor, const gfx::Rect& aScreenRect,
     41                         size_t aStep) = 0;
     42 
     43  const char* ToString() { return mTestName; }
     44 
     45 private:
     46  const char* mTestName;
     47 };
     48 
     49 static void DrawFrameTrivialQuad(Compositor* aCompositor,
     50                                 const gfx::Rect& aScreenRect, size_t aStep,
     51                                 const EffectChain& effects) {
     52  for (size_t i = 0; i < aStep * 10; i++) {
     53    const gfx::Rect& rect = gfx::Rect(i % (int)aScreenRect.width,
     54                                      (int)(i / aScreenRect.height), 1, 1);
     55    const gfx::Rect& clipRect = aScreenRect;
     56 
     57    float opacity = 1.f;
     58 
     59    gfx::Matrix transform2d;
     60 
     61    gfx::Matrix4x4 transform = gfx::Matrix4x4::From2D(transform2d);
     62 
     63    aCompositor->DrawQuad(rect, clipRect, effects, opacity, transform);
     64  }
     65 }
     66 
     67 static void DrawFrameStressQuad(Compositor* aCompositor,
     68                                const gfx::Rect& aScreenRect, size_t aStep,
     69                                const EffectChain& effects) {
     70  for (size_t i = 0; i < aStep * 10; i++) {
     71    const gfx::Rect& rect =
     72        gfx::Rect(aScreenRect.width * SimplePseudoRandom(i, 0),
     73                  aScreenRect.height * SimplePseudoRandom(i, 1),
     74                  aScreenRect.width * SimplePseudoRandom(i, 2),
     75                  aScreenRect.height * SimplePseudoRandom(i, 3));
     76    const gfx::Rect& clipRect = aScreenRect;
     77 
     78    float opacity = 1.f;
     79 
     80    gfx::Matrix transform2d;
     81    transform2d = transform2d.PreRotate(SimplePseudoRandom(i, 4) * 70.f);
     82 
     83    gfx::Matrix4x4 transform = gfx::Matrix4x4::From2D(transform2d);
     84 
     85    aCompositor->DrawQuad(rect, clipRect, effects, opacity, transform);
     86  }
     87 }
     88 
     89 class EffectSolidColorBench : public BenchTest {
     90 public:
     91  EffectSolidColorBench()
     92      : BenchTest("EffectSolidColorBench (clear frame with EffectSolidColor)") {
     93  }
     94 
     95  void DrawFrame(Compositor* aCompositor, const gfx::Rect& aScreenRect,
     96                 size_t aStep) {
     97    float tmp;
     98    float red = modff(aStep * 0.03f, &tmp);
     99    EffectChain effects;
    100    effects.mPrimaryEffect =
    101        new EffectSolidColor(gfx::DeviceColor(red, 0.4f, 0.4f, 1.0f));
    102 
    103    const gfx::Rect& rect = aScreenRect;
    104    const gfx::Rect& clipRect = aScreenRect;
    105 
    106    float opacity = 1.f;
    107 
    108    gfx::Matrix4x4 transform;
    109    aCompositor->DrawQuad(rect, clipRect, effects, opacity, transform);
    110  }
    111 };
    112 
    113 class EffectSolidColorTrivialBench : public BenchTest {
    114 public:
    115  EffectSolidColorTrivialBench()
    116      : BenchTest("EffectSolidColorTrivialBench (10s 1x1 EffectSolidColor)") {}
    117 
    118  void DrawFrame(Compositor* aCompositor, const gfx::Rect& aScreenRect,
    119                 size_t aStep) {
    120    EffectChain effects;
    121    effects.mPrimaryEffect = CreateEffect(aStep);
    122 
    123    DrawFrameTrivialQuad(aCompositor, aScreenRect, aStep, effects);
    124  }
    125 
    126  already_AddRefed<Effect> CreateEffect(size_t i) {
    127    float tmp;
    128    float red = modff(i * 0.03f, &tmp);
    129    EffectChain effects;
    130    return MakeAndAddRef<EffectSolidColor>(
    131        gfx::DeviceColor(red, 0.4f, 0.4f, 1.0f));
    132  }
    133 };
    134 
    135 class EffectSolidColorStressBench : public BenchTest {
    136 public:
    137  EffectSolidColorStressBench()
    138      : BenchTest(
    139            "EffectSolidColorStressBench (10s various EffectSolidColor)") {}
    140 
    141  void DrawFrame(Compositor* aCompositor, const gfx::Rect& aScreenRect,
    142                 size_t aStep) {
    143    EffectChain effects;
    144    effects.mPrimaryEffect = CreateEffect(aStep);
    145 
    146    DrawFrameStressQuad(aCompositor, aScreenRect, aStep, effects);
    147  }
    148 
    149  already_AddRefed<Effect> CreateEffect(size_t i) {
    150    float tmp;
    151    float red = modff(i * 0.03f, &tmp);
    152    EffectChain effects;
    153    return MakeAndAddRef<EffectSolidColor>(
    154        gfx::DeviceColor(red, 0.4f, 0.4f, 1.0f));
    155  }
    156 };
    157 
    158 class UploadBench : public BenchTest {
    159 public:
    160  UploadBench() : BenchTest("Upload Bench (10s 256x256 upload)") {}
    161 
    162  uint32_t* mBuf;
    163  RefPtr<DataSourceSurface> mSurface;
    164  RefPtr<DataTextureSource> mTexture;
    165 
    166  virtual void Setup(Compositor* aCompositor, size_t aStep) {
    167    int bytesPerPixel = 4;
    168    int w = 256;
    169    int h = 256;
    170    mBuf = (uint32_t*)malloc(w * h * sizeof(uint32_t));
    171 
    172    mSurface = Factory::CreateWrappingDataSourceSurface(
    173        reinterpret_cast<uint8_t*>(mBuf), w * bytesPerPixel, IntSize(w, h),
    174        SurfaceFormat::B8G8R8A8);
    175    mTexture = aCompositor->CreateDataTextureSource();
    176  }
    177 
    178  virtual void Teardown(Compositor* aCompositor) {
    179    mSurface = nullptr;
    180    mTexture = nullptr;
    181    free(mBuf);
    182  }
    183 
    184  void DrawFrame(Compositor* aCompositor, const gfx::Rect& aScreenRect,
    185                 size_t aStep) {
    186    for (size_t i = 0; i < aStep * 10; i++) {
    187      mTexture->Update(mSurface);
    188    }
    189  }
    190 };
    191 
    192 class TrivialTexturedQuadBench : public BenchTest {
    193 public:
    194  TrivialTexturedQuadBench()
    195      : BenchTest("Trvial Textured Quad (10s 256x256 quads)") {}
    196 
    197  uint32_t* mBuf;
    198  RefPtr<DataSourceSurface> mSurface;
    199  RefPtr<DataTextureSource> mTexture;
    200 
    201  virtual void Setup(Compositor* aCompositor, size_t aStep) {
    202    int bytesPerPixel = 4;
    203    size_t w = 256;
    204    size_t h = 256;
    205    mBuf = (uint32_t*)malloc(w * h * sizeof(uint32_t));
    206    for (size_t i = 0; i < w * h; i++) {
    207      mBuf[i] = 0xFF00008F;
    208    }
    209 
    210    mSurface = Factory::CreateWrappingDataSourceSurface(
    211        reinterpret_cast<uint8_t*>(mBuf), w * bytesPerPixel, IntSize(w, h),
    212        SurfaceFormat::B8G8R8A8);
    213    mTexture = aCompositor->CreateDataTextureSource();
    214    mTexture->Update(mSurface);
    215  }
    216 
    217  void DrawFrame(Compositor* aCompositor, const gfx::Rect& aScreenRect,
    218                 size_t aStep) {
    219    EffectChain effects;
    220    effects.mPrimaryEffect = CreateEffect(aStep);
    221 
    222    DrawFrameTrivialQuad(aCompositor, aScreenRect, aStep, effects);
    223  }
    224 
    225  virtual void Teardown(Compositor* aCompositor) {
    226    mSurface = nullptr;
    227    mTexture = nullptr;
    228    free(mBuf);
    229  }
    230 
    231  already_AddRefed<Effect> CreateEffect(size_t i) {
    232    return CreateTexturedEffect(SurfaceFormat::B8G8R8A8, mTexture,
    233                                SamplingFilter::POINT, true);
    234  }
    235 };
    236 
    237 class StressTexturedQuadBench : public BenchTest {
    238 public:
    239  StressTexturedQuadBench()
    240      : BenchTest("Stress Textured Quad (10s 256x256 quads)") {}
    241 
    242  uint32_t* mBuf;
    243  RefPtr<DataSourceSurface> mSurface;
    244  RefPtr<DataTextureSource> mTexture;
    245 
    246  virtual void Setup(Compositor* aCompositor, size_t aStep) {
    247    int bytesPerPixel = 4;
    248    size_t w = 256;
    249    size_t h = 256;
    250    mBuf = (uint32_t*)malloc(w * h * sizeof(uint32_t));
    251    for (size_t i = 0; i < w * h; i++) {
    252      mBuf[i] = 0xFF00008F;
    253    }
    254 
    255    mSurface = Factory::CreateWrappingDataSourceSurface(
    256        reinterpret_cast<uint8_t*>(mBuf), w * bytesPerPixel, IntSize(w, h),
    257        SurfaceFormat::B8G8R8A8);
    258    mTexture = aCompositor->CreateDataTextureSource();
    259    mTexture->Update(mSurface);
    260  }
    261 
    262  void DrawFrame(Compositor* aCompositor, const gfx::Rect& aScreenRect,
    263                 size_t aStep) {
    264    EffectChain effects;
    265    effects.mPrimaryEffect = CreateEffect(aStep);
    266 
    267    DrawFrameStressQuad(aCompositor, aScreenRect, aStep, effects);
    268  }
    269 
    270  virtual void Teardown(Compositor* aCompositor) {
    271    mSurface = nullptr;
    272    mTexture = nullptr;
    273    free(mBuf);
    274  }
    275 
    276  virtual already_AddRefed<Effect> CreateEffect(size_t i) {
    277    return CreateTexturedEffect(SurfaceFormat::B8G8R8A8, mTexture,
    278                                SamplingFilter::POINT, true);
    279  }
    280 };
    281 
    282 static void RunCompositorBench(Compositor* aCompositor,
    283                               const gfx::Rect& aScreenRect) {
    284  std::vector<BenchTest*> tests;
    285 
    286  tests.push_back(new EffectSolidColorBench());
    287  tests.push_back(new UploadBench());
    288  tests.push_back(new EffectSolidColorTrivialBench());
    289  tests.push_back(new EffectSolidColorStressBench());
    290  tests.push_back(new TrivialTexturedQuadBench());
    291  tests.push_back(new StressTexturedQuadBench());
    292 
    293  for (size_t i = 0; i < tests.size(); i++) {
    294    BenchTest* test = tests[i];
    295    std::vector<TimeDuration> results;
    296    int testsOverThreshold = 0;
    297    PROFILER_MARKER_UNTYPED(
    298        ProfilerString8View::WrapNullTerminatedString(test->ToString()),
    299        GRAPHICS);
    300    for (size_t j = 0; j < TEST_STEPS; j++) {
    301      test->Setup(aCompositor, j);
    302 
    303      TimeStamp start = TimeStamp::Now();
    304      IntRect screenRect(aScreenRect.x, aScreenRect.y, aScreenRect.width,
    305                         aScreenRect.height);
    306      aCompositor->BeginFrame(IntRect(screenRect.x, screenRect.y,
    307                                      screenRect.width, screenRect.height),
    308                              nullptr, aScreenRect, nullptr, nullptr);
    309 
    310      test->DrawFrame(aCompositor, aScreenRect, j);
    311 
    312      aCompositor->EndFrame();
    313      results.push_back(TimeStamp::Now() - start);
    314 
    315      if (results[j].ToMilliseconds() > DURATION_THRESHOLD) {
    316        testsOverThreshold++;
    317        if (testsOverThreshold == THRESHOLD_ABORT_COUNT) {
    318          test->Teardown(aCompositor);
    319          break;
    320        }
    321      } else {
    322        testsOverThreshold = 0;
    323      }
    324      test->Teardown(aCompositor);
    325    }
    326 
    327    printf_stderr("%s\n", test->ToString());
    328    printf_stderr("Run step, Time (ms)\n");
    329    for (size_t j = 0; j < results.size(); j++) {
    330      printf_stderr("%i,%f\n", j, (float)results[j].ToMilliseconds());
    331    }
    332    printf_stderr("\n", test->ToString());
    333  }
    334 
    335  for (size_t i = 0; i < tests.size(); i++) {
    336    delete tests[i];
    337  }
    338 }
    339 
    340 void CompositorBench(Compositor* aCompositor, const gfx::IntRect& aScreenRect) {
    341  static bool sRanBenchmark = false;
    342  bool wantBenchmark = StaticPrefs::layers_bench_enabled();
    343  if (wantBenchmark && !sRanBenchmark) {
    344    RunCompositorBench(aCompositor, aScreenRect);
    345  }
    346  sRanBenchmark = wantBenchmark;
    347 }
    348 
    349 }  // namespace layers
    350 }  // namespace mozilla
    351 
    352 #endif