void RenderViewMLGPU::AddItemFrontToBack(LayerMLGPU* aLayer, ItemInfo& aItem) {
  // We receive items in front-to-back order. Ideally we want to push items
  // as far back into batches impossible, to ensure the GPU can do a good
  // job at culling. However we also want to make sure we actually batch
  // items versus drawing one primitive per pass.
  //
  // As a compromise we look at the most 3 recent batches and then give up.
  // This can be tweaked in the future.
  static const size_t kMaxSearch = 3;
  size_t iterations = 0;
  for (auto iter = mFrontToBack.rbegin(); iter != mFrontToBack.rend(); iter++) {
    RenderPassMLGPU* pass = (*iter);
    if (pass->IsCompatible(aItem) && pass->AcceptItem(aItem)) {
      AL_LOG("RenderView %p added layer %p to pass %p (%d)\n", this,
             aLayer->GetLayer(), pass, int(pass->GetType()));
      return;
    }
    if (++iterations > kMaxSearch) {
      break;
    }
  }

  RefPtr<RenderPassMLGPU> pass = RenderPassMLGPU::CreatePass(mBuilder, aItem);
  if (!pass || !pass->AcceptItem(aItem)) {
    MOZ_ASSERT_UNREACHABLE("Could not build a pass for item!");
    return;
  }
  AL_LOG("RenderView %p added layer %p to new pass %p (%d)\n", this,
         aLayer->GetLayer(), pass.get(), int(pass->GetType()));

  mFrontToBack.push_back(pass);
}
void RenderViewMLGPU::AddItemBackToFront(LayerMLGPU* aLayer, ItemInfo& aItem) {
  // We receive layers in front-to-back order, but there are two cases when we
  // actually draw back-to-front: when the depth buffer is disabled, or when
  // using the depth buffer and the item has transparent pixels (and therefore
  // requires blending). In these cases we will build vertex and constant
  // buffers in reverse, as well as execute batches in reverse, to ensure the
  // correct ordering.
  //
  // Note: We limit the number of batches we search through, since it's better
  // to add new draw calls than spend too much time finding compatible
  // batches further down.
  static const size_t kMaxSearch = 10;
  size_t iterations = 0;
  for (auto iter = mBackToFront.begin(); iter != mBackToFront.end(); iter++) {
    RenderPassMLGPU* pass = (*iter);
    if (pass->IsCompatible(aItem) && pass->AcceptItem(aItem)) {
      AL_LOG("RenderView %p added layer %p to pass %p (%d)\n", this,
             aLayer->GetLayer(), pass, int(pass->GetType()));
      return;
    }
    if (pass->Intersects(aItem)) {
      break;
    }
    if (++iterations > kMaxSearch) {
      break;
    }
  }

  RefPtr<RenderPassMLGPU> pass = RenderPassMLGPU::CreatePass(mBuilder, aItem);
  if (!pass || !pass->AcceptItem(aItem)) {
    MOZ_ASSERT_UNREACHABLE("Could not build a pass for item!");
    return;
  }
  AL_LOG("RenderView %p added layer %p to new pass %p (%d)\n", this,
         aLayer->GetLayer(), pass.get(), int(pass->GetType()));

  mBackToFront.push_front(pass);
}