# Global Metrics

path: .metrics.nexits.average
old: 0.6666666666666666
new: 1.1162790697674418
path: .metrics.nexits.sum
old: 2.0
new: 48.0
path: .metrics.cyclomatic.average
old: 3.0
new: 2.2452830188679247
path: .metrics.cyclomatic.sum
old: 12.0
new: 119.0
path: .metrics.nargs.average
old: 1.6666666666666667
new: 0.6744186046511628
path: .metrics.nargs.sum
old: 5.0
new: 29.0
path: .metrics.loc.lloc
old: 5.0
new: 214.0
path: .metrics.loc.blank
old: 50.0
new: 105.0
path: .metrics.loc.cloc
old: 43.0
new: 52.0
path: .metrics.loc.sloc
old: 288.0
new: 675.0
path: .metrics.loc.ploc
old: 195.0
new: 518.0
path: .metrics.halstead.N1
old: 247.0
new: 1491.0
path: .metrics.halstead.bugs
old: 0.7130407462111065
new: 4.544279849278452
path: .metrics.halstead.n1
old: 20.0
new: 37.0
path: .metrics.halstead.estimated_program_length
old: 1231.6940194737326
new: 1858.611237190005
path: .metrics.halstead.length
old: 596.0
new: 2441.0
path: .metrics.halstead.purity_ratio
old: 2.066600703814988
new: 0.7614138620196662
path: .metrics.halstead.time
old: 5496.432501201217
new: 88431.4975850394
path: .metrics.halstead.volume
old: 4450.692907849467
new: 19472.540293263297
path: .metrics.halstead.effort
old: 98935.78502162192
new: 1591766.956530709
path: .metrics.halstead.level
old: 0.04498567335243553
new: 0.012233285917496443
path: .metrics.halstead.N2
old: 349.0
new: 950.0
path: .metrics.halstead.difficulty
old: 22.22929936305733
new: 81.74418604651163
path: .metrics.halstead.n2
old: 157.0
new: 215.0
path: .metrics.halstead.vocabulary
old: 177.0
new: 252.0
path: .metrics.mi.mi_visual_studio
old: 19.19052739410797
new: 0.0
path: .metrics.mi.mi_sei
old: 1.0388958348046202
new: -61.88229299670572
path: .metrics.mi.mi_original
old: 32.81580184392463
new: -13.26750051469783
path: .metrics.cognitive.average
old: 2.0
new: 1.372093023255814
path: .metrics.cognitive.sum
old: 6.0
new: 59.0
path: .metrics.nom.closures
old: 0.0
new: 1.0
path: .metrics.nom.functions
old: 3.0
new: 42.0
path: .metrics.nom.total
old: 3.0
new: 43.0

# Spaces Data

## Minimal test - lines (11, 675)

path: .spaces[0].metrics.cyclomatic.average
old: 1.0
new: 2.269230769230769
path: .spaces[0].metrics.cyclomatic.sum
old: 1.0
new: 118.0
path: .spaces[0].metrics.nom.functions
old: 1.0
new: 42.0
path: .spaces[0].metrics.nom.total
old: 1.0
new: 43.0
path: .spaces[0].metrics.nom.closures
old: 0.0
new: 1.0
path: .spaces[0].metrics.nargs.average
old: 3.0
new: 0.6744186046511628
path: .spaces[0].metrics.nargs.sum
old: 3.0
new: 29.0
path: .spaces[0].metrics.cognitive.average
old: 0.0
new: 1.372093023255814
path: .spaces[0].metrics.cognitive.sum
old: 0.0
new: 59.0
path: .spaces[0].metrics.halstead.time
old: 27.782333124327245
new: 88872.68454594695
path: .spaces[0].metrics.halstead.estimated_program_length
old: 44.039100017307746
new: 1840.2429236363748
path: .spaces[0].metrics.halstead.bugs
old: 0.02100097985297437
new: 4.559381660232157
path: .spaces[0].metrics.halstead.difficulty
old: 4.0
new: 82.33802816901408
path: .spaces[0].metrics.halstead.vocabulary
old: 15.0
new: 250.0
path: .spaces[0].metrics.halstead.volume
old: 125.0204990594726
new: 19428.54787029083
path: .spaces[0].metrics.halstead.n2
old: 9.0
new: 213.0
path: .spaces[0].metrics.halstead.effort
old: 500.0819962378904
new: 1599708.321827045
path: .spaces[0].metrics.halstead.level
old: 0.25
new: 0.012145056448853915
path: .spaces[0].metrics.halstead.n1
old: 6.0
new: 37.0
path: .spaces[0].metrics.halstead.purity_ratio
old: 1.376221875540867
new: 0.7545071437623513
path: .spaces[0].metrics.halstead.N1
old: 20.0
new: 1491.0
path: .spaces[0].metrics.halstead.N2
old: 12.0
new: 948.0
path: .spaces[0].metrics.halstead.length
old: 32.0
new: 2439.0
path: .spaces[0].metrics.loc.blank
old: 0.0
new: 104.0
path: .spaces[0].metrics.loc.lloc
old: 2.0
new: 214.0
path: .spaces[0].metrics.loc.sloc
old: 7.0
new: 665.0
path: .spaces[0].metrics.loc.ploc
old: 7.0
new: 514.0
path: .spaces[0].metrics.loc.cloc
old: 0.0
new: 47.0
path: .spaces[0].metrics.mi.mi_original
old: 114.13817146037346
new: -12.783943834763464
path: .spaces[0].metrics.mi.mi_visual_studio
old: 66.74746869027688
new: 0.0
path: .spaces[0].metrics.mi.mi_sei
old: 89.06754180940669
new: -62.11397268830072
path: .spaces[0].metrics.nexits.sum
old: 0.0
new: 48.0
path: .spaces[0].metrics.nexits.average
old: 0.0
new: 1.1162790697674418

### Code

    namespace mozilla {
    namespace widget {
    namespace remote_backbuffer {

    // This number can be adjusted as a time-memory tradeoff
    constexpr uint8_t kMaxDirtyRects = 8;

    struct IpcSafeRect {
      explicit IpcSafeRect(const gfx::IntRect& aRect)
          : x(aRect.x), y(aRect.y), width(aRect.width), height(aRect.height) {}
      int32_t x;
      int32_t y;
      int32_t width;
      int32_t height;
    };

    enum class ResponseResult {
      Unknown,
      Error,
      BorrowSuccess,
      BorrowSameBuffer,
      PresentSuccess
    };

    enum class SharedDataType {
      BorrowRequest,
      BorrowRequestAllowSameBuffer,
      BorrowResponse,
      PresentRequest,
      PresentResponse
    };

    struct BorrowResponseData {
      ResponseResult result;
      int32_t width;
      int32_t height;
      HANDLE fileMapping;
    };

    struct PresentRequestData {
      uint8_t lenDirtyRects;
      IpcSafeRect dirtyRects[kMaxDirtyRects];
    };

    struct PresentResponseData {
      ResponseResult result;
    };

    struct SharedData {
      SharedDataType dataType;
      union {
        BorrowResponseData borrowResponse;
        PresentRequestData presentRequest;
        PresentResponseData presentResponse;
      } data;
    };

    static_assert(std::is_trivially_copyable::value &&
                      std::is_standard_layout::value,
                  "SharedData must be safe to pass over IPC boundaries");

    class SharedImage {
     public:
      SharedImage()
          : mWidth(0), mHeight(0), mFileMapping(nullptr), mPixelData(nullptr) {}

      ~SharedImage() {
        if (mPixelData) {
          MOZ_ALWAYS_TRUE(::UnmapViewOfFile(mPixelData));
        }

        if (mFileMapping) {
          MOZ_ALWAYS_TRUE(::CloseHandle(mFileMapping));
        }
      }

      bool Initialize(int32_t aWidth, int32_t aHeight) {
        MOZ_ASSERT(aWidth > 0);
        MOZ_ASSERT(aHeight > 0);

        mWidth = aWidth;
        mHeight = aHeight;

        DWORD bufferSize = static_cast(mHeight * GetStride());

        mFileMapping = ::CreateFileMappingW(
            INVALID_HANDLE_VALUE, nullptr /*secattr*/, PAGE_READWRITE,
            0 /*sizeHigh*/, bufferSize, nullptr /*name*/);
        if (!mFileMapping) {
          return false;
        }

        void* mappedFilePtr =
            ::MapViewOfFile(mFileMapping, FILE_MAP_ALL_ACCESS, 0 /*offsetHigh*/,
                            0 /*offsetLow*/, 0 /*bytesToMap*/);
        if (!mappedFilePtr) {
          return false;
        }

        mPixelData = reinterpret_cast(mappedFilePtr);

        return true;
      }

      bool InitializeRemote(int32_t aWidth, int32_t aHeight, HANDLE aFileMapping) {
        MOZ_ASSERT(aWidth > 0);
        MOZ_ASSERT(aHeight > 0);
        MOZ_ASSERT(aFileMapping);

        mWidth = aWidth;
        mHeight = aHeight;
        mFileMapping = aFileMapping;

        void* mappedFilePtr =
            ::MapViewOfFile(mFileMapping, FILE_MAP_ALL_ACCESS, 0 /*offsetHigh*/,
                            0 /*offsetLow*/, 0 /*bytesToMap*/);
        if (!mappedFilePtr) {
          return false;
        }

        mPixelData = reinterpret_cast(mappedFilePtr);

        return true;
      }

      HBITMAP CreateDIBSection() {
        BITMAPINFO bitmapInfo = {};
        bitmapInfo.bmiHeader.biSize = sizeof(bitmapInfo.bmiHeader);
        bitmapInfo.bmiHeader.biWidth = mWidth;
        bitmapInfo.bmiHeader.biHeight = -mHeight;
        bitmapInfo.bmiHeader.biPlanes = 1;
        bitmapInfo.bmiHeader.biBitCount = 32;
        bitmapInfo.bmiHeader.biCompression = BI_RGB;
        void* dummy = nullptr;
        return ::CreateDIBSection(nullptr /*paletteDC*/, &bitmapInfo,
                                  DIB_RGB_COLORS, &dummy, mFileMapping,
                                  0 /*offset*/);
      }

      HANDLE CreateRemoteFileMapping(DWORD aTargetProcessId) {
        MOZ_ASSERT(aTargetProcessId);

        HANDLE fileMapping = nullptr;
        if (!ipc::DuplicateHandle(mFileMapping, aTargetProcessId, &fileMapping,
                                  0 /*desiredAccess*/, DUPLICATE_SAME_ACCESS)) {
          return nullptr;
        }
        return fileMapping;
      }

      already_AddRefed CreateDrawTarget() {
        return gfx::Factory::CreateDrawTargetForData(
            gfx::BackendType::CAIRO, mPixelData, IntSize(mWidth, mHeight),
            GetStride(), gfx::SurfaceFormat::B8G8R8A8);
      }

      void CopyPixelsFrom(const SharedImage& other) {
        const unsigned char* src = other.mPixelData;
        unsigned char* dst = mPixelData;

        int32_t width = std::min(mWidth, other.mWidth);
        int32_t height = std::min(mHeight, other.mHeight);

        for (int32_t row = 0; row < height; ++row) {
          memcpy(dst, src, static_cast(width * kBytesPerPixel));
          src += other.GetStride();
          dst += GetStride();
        }
      }

      int32_t GetWidth() { return mWidth; }

      int32_t GetHeight() { return mHeight; }

      SharedImage(const SharedImage&) = delete;
      SharedImage(SharedImage&&) = delete;
      SharedImage& operator=(const SharedImage&) = delete;
      SharedImage& operator=(SharedImage&&) = delete;

     private:
      static constexpr int32_t kBytesPerPixel = 4;

      int32_t GetStride() const {
        // DIB requires 32-bit row alignment
        return (((mWidth * kBytesPerPixel) + 3) / 4) * 4;
      }

      int32_t mWidth;
      int32_t mHeight;
      HANDLE mFileMapping;
      unsigned char* mPixelData;
    };

    class PresentableSharedImage {
     public:
      PresentableSharedImage()
          : mSharedImage(),
            mDeviceContext(nullptr),
            mDIBSection(nullptr),
            mSavedObject(nullptr) {}

      ~PresentableSharedImage() {
        if (mSavedObject) {
          MOZ_ALWAYS_TRUE(::SelectObject(mDeviceContext, mSavedObject));
        }

        if (mDIBSection) {
          MOZ_ALWAYS_TRUE(::DeleteObject(mDIBSection));
        }

        if (mDeviceContext) {
          MOZ_ALWAYS_TRUE(::DeleteDC(mDeviceContext));
        }
      }

      bool Initialize(int32_t aWidth, int32_t aHeight) {
        if (!mSharedImage.Initialize(aWidth, aHeight)) {
          return false;
        }

        mDeviceContext = ::CreateCompatibleDC(nullptr);
        if (!mDeviceContext) {
          return false;
        }

        mDIBSection = mSharedImage.CreateDIBSection();
        if (!mDIBSection) {
          return false;
        }

        mSavedObject = ::SelectObject(mDeviceContext, mDIBSection);
        if (!mSavedObject) {
          return false;
        }

        return true;
      }

      bool PresentToWindow(HWND aWindowHandle, nsTransparencyMode aTransparencyMode,
                           Span aDirtyRects) {
        if (aTransparencyMode == eTransparencyTransparent) {
          // If our window is a child window or a child-of-a-child, the window
          // that needs to be updated is the top level ancestor of the tree
          HWND topLevelWindow = WinUtils::GetTopLevelHWND(aWindowHandle, true);
          MOZ_ASSERT(::GetWindowLongPtr(topLevelWindow, GWL_EXSTYLE) &
                     WS_EX_LAYERED);

          BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
          SIZE winSize = {mSharedImage.GetWidth(), mSharedImage.GetHeight()};
          POINT srcPos = {0, 0};
          return !!::UpdateLayeredWindow(
              topLevelWindow, nullptr /*paletteDC*/, nullptr /*newPos*/, &winSize,
              mDeviceContext, &srcPos, 0 /*colorKey*/, &bf, ULW_ALPHA);
        }

        IntRect sharedImageRect{0, 0, mSharedImage.GetWidth(),
                                mSharedImage.GetHeight()};

        bool result = true;

        HDC windowDC = ::GetDC(aWindowHandle);
        if (!windowDC) {
          return false;
        }

        for (auto& ipcDirtyRect : aDirtyRects) {
          IntRect dirtyRect{ipcDirtyRect.x, ipcDirtyRect.y, ipcDirtyRect.width,
                            ipcDirtyRect.height};
          IntRect bltRect = dirtyRect.Intersect(sharedImageRect);

          if (!::BitBlt(windowDC, bltRect.x /*dstX*/, bltRect.y /*dstY*/,
                        bltRect.width, bltRect.height, mDeviceContext,
                        bltRect.x /*srcX*/, bltRect.y /*srcY*/, SRCCOPY)) {
            result = false;
            break;
          }
        }

        MOZ_ALWAYS_TRUE(::ReleaseDC(aWindowHandle, windowDC));

        return result;
      }

      HANDLE CreateRemoteFileMapping(DWORD aTargetProcessId) {
        return mSharedImage.CreateRemoteFileMapping(aTargetProcessId);
      }

      already_AddRefed CreateDrawTarget() {
        return mSharedImage.CreateDrawTarget();
      }

      void CopyPixelsFrom(const PresentableSharedImage& other) {
        mSharedImage.CopyPixelsFrom(other.mSharedImage);
      }

      int32_t GetWidth() { return mSharedImage.GetWidth(); }

      int32_t GetHeight() { return mSharedImage.GetHeight(); }

      PresentableSharedImage(const PresentableSharedImage&) = delete;
      PresentableSharedImage(PresentableSharedImage&&) = delete;
      PresentableSharedImage& operator=(const PresentableSharedImage&) = delete;
      PresentableSharedImage& operator=(PresentableSharedImage&&) = delete;

     private:
      SharedImage mSharedImage;
      HDC mDeviceContext;
      HBITMAP mDIBSection;
      HGDIOBJ mSavedObject;
    };

    Provider::Provider()
        : mWindowHandle(nullptr),
          mTargetProcessId(0),
          mFileMapping(nullptr),
          mRequestReadyEvent(nullptr),
          mResponseReadyEvent(nullptr),
          mSharedDataPtr(nullptr),
          mStopServiceThread(false),
          mServiceThread(),
          mBackbuffer() {}

    Provider::~Provider() {
      mBackbuffer.reset();

      if (mServiceThread.joinable()) {
        mStopServiceThread = true;
        MOZ_ALWAYS_TRUE(::SetEvent(mRequestReadyEvent));
        mServiceThread.join();
      }

      if (mSharedDataPtr) {
        MOZ_ALWAYS_TRUE(::UnmapViewOfFile(mSharedDataPtr));
      }

      if (mResponseReadyEvent) {
        MOZ_ALWAYS_TRUE(::CloseHandle(mResponseReadyEvent));
      }

      if (mRequestReadyEvent) {
        MOZ_ALWAYS_TRUE(::CloseHandle(mRequestReadyEvent));
      }

      if (mFileMapping) {
        MOZ_ALWAYS_TRUE(::CloseHandle(mFileMapping));
      }
    }

    bool Provider::Initialize(HWND aWindowHandle, DWORD aTargetProcessId,
                              nsTransparencyMode aTransparencyMode) {
      MOZ_ASSERT(aWindowHandle);
      MOZ_ASSERT(aTargetProcessId);

      mWindowHandle = aWindowHandle;
      mTargetProcessId = aTargetProcessId;

      mFileMapping = ::CreateFileMappingW(
          INVALID_HANDLE_VALUE, nullptr /*secattr*/, PAGE_READWRITE, 0 /*sizeHigh*/,
          static_cast(sizeof(SharedData)), nullptr /*name*/);
      if (!mFileMapping) {
        return false;
      }

      mRequestReadyEvent =
          ::CreateEventW(nullptr /*secattr*/, FALSE /*manualReset*/,
                         FALSE /*initialState*/, nullptr /*name*/);
      if (!mRequestReadyEvent) {
        return false;
      }

      mResponseReadyEvent =
          ::CreateEventW(nullptr /*secattr*/, FALSE /*manualReset*/,
                         FALSE /*initialState*/, nullptr /*name*/);
      if (!mResponseReadyEvent) {
        return false;
      }

      void* mappedFilePtr =
          ::MapViewOfFile(mFileMapping, FILE_MAP_ALL_ACCESS, 0 /*offsetHigh*/,
                          0 /*offsetLow*/, 0 /*bytesToMap*/);
      if (!mappedFilePtr) {
        return false;
      }

      mSharedDataPtr = reinterpret_cast(mappedFilePtr);

      mStopServiceThread = false;

      mServiceThread = std::thread([this] { this->ThreadMain(); });

      mTransparencyMode = aTransparencyMode;

      return true;
    }

    Maybe Provider::CreateRemoteHandles() {
      HANDLE fileMapping = nullptr;
      if (!ipc::DuplicateHandle(mFileMapping, mTargetProcessId, &fileMapping,
                                0 /*desiredAccess*/, DUPLICATE_SAME_ACCESS)) {
        return Nothing();
      }

      HANDLE requestReadyEvent = nullptr;
      if (!ipc::DuplicateHandle(mRequestReadyEvent, mTargetProcessId,
                                &requestReadyEvent, 0 /*desiredAccess*/,
                                DUPLICATE_SAME_ACCESS)) {
        return Nothing();
      }

      HANDLE responseReadyEvent = nullptr;
      if (!ipc::DuplicateHandle(mResponseReadyEvent, mTargetProcessId,
                                &responseReadyEvent, 0 /*desiredAccess*/,
                                DUPLICATE_SAME_ACCESS)) {
        return Nothing();
      }

      return Some(RemoteBackbufferHandles(
          reinterpret_cast(fileMapping),
          reinterpret_cast(requestReadyEvent),
          reinterpret_cast(responseReadyEvent)));
    }

    void Provider::UpdateTransparencyMode(nsTransparencyMode aTransparencyMode) {
      mTransparencyMode = aTransparencyMode;
    }

    void Provider::ThreadMain() {
      while (true) {
        MOZ_ALWAYS_TRUE(::WaitForSingleObject(mRequestReadyEvent, INFINITE) ==
                        WAIT_OBJECT_0);

        if (mStopServiceThread) {
          break;
        }

        switch (mSharedDataPtr->dataType) {
          case SharedDataType::BorrowRequest:
          case SharedDataType::BorrowRequestAllowSameBuffer: {
            BorrowResponseData responseData = {};

            HandleBorrowRequest(&responseData,
                                mSharedDataPtr->dataType ==
                                    SharedDataType::BorrowRequestAllowSameBuffer);

            mSharedDataPtr->dataType = SharedDataType::BorrowResponse;
            mSharedDataPtr->data.borrowResponse = responseData;

            MOZ_ALWAYS_TRUE(::SetEvent(mResponseReadyEvent));

            break;
          }
          case SharedDataType::PresentRequest: {
            PresentRequestData requestData = mSharedDataPtr->data.presentRequest;
            PresentResponseData responseData = {};

            HandlePresentRequest(requestData, &responseData);

            mSharedDataPtr->dataType = SharedDataType::PresentResponse;
            mSharedDataPtr->data.presentResponse = responseData;

            MOZ_ALWAYS_TRUE(::SetEvent(mResponseReadyEvent));

            break;
          }
          default:
            break;
        };
      }
    }

    void Provider::HandleBorrowRequest(BorrowResponseData* aResponseData,
                                       bool aAllowSameBuffer) {
      MOZ_ASSERT(aResponseData);

      aResponseData->result = ResponseResult::Error;

      RECT clientRect = {};
      if (!::GetClientRect(mWindowHandle, &clientRect)) {
        return;
      }

      MOZ_ASSERT(clientRect.left == 0);
      MOZ_ASSERT(clientRect.top == 0);

      int32_t width = clientRect.right ? clientRect.right : 1;
      int32_t height = clientRect.bottom ? clientRect.bottom : 1;

      bool needNewBackbuffer = !aAllowSameBuffer || !mBackbuffer ||
                               (mBackbuffer->GetWidth() != width) ||
                               (mBackbuffer->GetHeight() != height);

      if (!needNewBackbuffer) {
        aResponseData->result = ResponseResult::BorrowSameBuffer;
        return;
      }

      auto newBackbuffer = std::make_unique();
      if (!newBackbuffer->Initialize(width, height)) {
        return;
      }

      // Preserve the contents of the old backbuffer (if it exists)
      if (mBackbuffer) {
        newBackbuffer->CopyPixelsFrom(*mBackbuffer);
        mBackbuffer.reset();
      }

      HANDLE remoteFileMapping =
          newBackbuffer->CreateRemoteFileMapping(mTargetProcessId);
      if (!remoteFileMapping) {
        return;
      }

      aResponseData->result = ResponseResult::BorrowSuccess;
      aResponseData->width = width;
      aResponseData->height = height;
      aResponseData->fileMapping = remoteFileMapping;

      mBackbuffer = std::move(newBackbuffer);
    }

    void Provider::HandlePresentRequest(const PresentRequestData& aRequestData,
                                        PresentResponseData* aResponseData) {
      MOZ_ASSERT(aResponseData);

      Span rectSpan(aRequestData.dirtyRects, kMaxDirtyRects);

      aResponseData->result = ResponseResult::Error;

      if (!mBackbuffer) {
        return;
      }

      if (!mBackbuffer->PresentToWindow(
              mWindowHandle, mTransparencyMode,
              rectSpan.First(aRequestData.lenDirtyRects))) {
        return;
      }

      aResponseData->result = ResponseResult::PresentSuccess;
    }

    Client::Client()
        : mFileMapping(nullptr),
          mRequestReadyEvent(nullptr),
          mResponseReadyEvent(nullptr),
          mSharedDataPtr(nullptr),
          mBackbuffer() {}

    Client::~Client() {
      mBackbuffer.reset();

      if (mSharedDataPtr) {
        MOZ_ALWAYS_TRUE(::UnmapViewOfFile(mSharedDataPtr));
      }

      if (mResponseReadyEvent) {
        MOZ_ALWAYS_TRUE(::CloseHandle(mResponseReadyEvent));
      }

      if (mRequestReadyEvent) {
        MOZ_ALWAYS_TRUE(::CloseHandle(mRequestReadyEvent));
      }

      if (mFileMapping) {
        MOZ_ALWAYS_TRUE(::CloseHandle(mFileMapping));
      }
    }

    bool Client::Initialize(const RemoteBackbufferHandles& aRemoteHandles) {
      MOZ_ASSERT(aRemoteHandles.fileMapping());
      MOZ_ASSERT(aRemoteHandles.requestReadyEvent());
      MOZ_ASSERT(aRemoteHandles.responseReadyEvent());

      mFileMapping = reinterpret_cast(aRemoteHandles.fileMapping());
      mRequestReadyEvent =
          reinterpret_cast(aRemoteHandles.requestReadyEvent());
      mResponseReadyEvent =
          reinterpret_cast(aRemoteHandles.responseReadyEvent());

      void* mappedFilePtr =
          ::MapViewOfFile(mFileMapping, FILE_MAP_ALL_ACCESS, 0 /*offsetHigh*/,
                          0 /*offsetLow*/, 0 /*bytesToMap*/);
      if (!mappedFilePtr) {
        return false;
      }

      mSharedDataPtr = reinterpret_cast(mappedFilePtr);

      return true;
    }

    already_AddRefed Client::BorrowDrawTarget() {
      mSharedDataPtr->dataType = mBackbuffer
                                     ? SharedDataType::BorrowRequestAllowSameBuffer
                                     : SharedDataType::BorrowRequest;

      MOZ_ALWAYS_TRUE(::SetEvent(mRequestReadyEvent));
      MOZ_ALWAYS_TRUE(::WaitForSingleObject(mResponseReadyEvent, INFINITE) ==
                      WAIT_OBJECT_0);

      if (mSharedDataPtr->dataType != SharedDataType::BorrowResponse) {
        return nullptr;
      }

      BorrowResponseData responseData = mSharedDataPtr->data.borrowResponse;

      if ((responseData.result != ResponseResult::BorrowSameBuffer) &&
          (responseData.result != ResponseResult::BorrowSuccess)) {
        return nullptr;
      }

      if (responseData.result == ResponseResult::BorrowSuccess) {
        mBackbuffer.reset();

        auto newBackbuffer = std::make_unique();
        if (!newBackbuffer->InitializeRemote(responseData.width,
                                             responseData.height,
                                             responseData.fileMapping)) {
          return nullptr;
        }

        mBackbuffer = std::move(newBackbuffer);
      }

      MOZ_ASSERT(mBackbuffer);

      return mBackbuffer->CreateDrawTarget();
    }

    bool Client::PresentDrawTarget(gfx::IntRegion aDirtyRegion) {
      mSharedDataPtr->dataType = SharedDataType::PresentRequest;

      // Simplify the region until it has <= kMaxDirtyRects
      aDirtyRegion.SimplifyOutward(kMaxDirtyRects);

      Span rectSpan(mSharedDataPtr->data.presentRequest.dirtyRects, kMaxDirtyRects);

      uint8_t rectIndex = 0;
      for (auto iter = aDirtyRegion.RectIter(); !iter.Done(); iter.Next()) {
        rectSpan[rectIndex] = IpcSafeRect(iter.Get());
        ++rectIndex;
      }

      mSharedDataPtr->data.presentRequest.lenDirtyRects = rectIndex;

      MOZ_ALWAYS_TRUE(::SetEvent(mRequestReadyEvent));
      MOZ_ALWAYS_TRUE(::WaitForSingleObject(mResponseReadyEvent, INFINITE) ==
                      WAIT_OBJECT_0);

      if (mSharedDataPtr->dataType != SharedDataType::PresentResponse) {
        return false;
      }

      if (mSharedDataPtr->data.presentResponse.result !=
          ResponseResult::PresentSuccess) {
        return false;
      }

      return true;
    }

    }  // namespace remote_backbuffer
    }  // namespace widget
    }  // namespace mozilla