// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gpu/command_buffer/client/share_group.h"

#include <stdint.h>

#include <vector>

#include "base/containers/stack.h"
#include "base/logging.h"
#include "base/synchronization/lock.h"
#include "gpu/command_buffer/client/gles2_cmd_helper.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "gpu/command_buffer/client/program_info_manager.h"
#include "gpu/command_buffer/common/id_allocator.h"

namespace gpu {
namespace gles2 {

ShareGroupContextData::IdHandlerData::IdHandlerData() : flush_generation_(0) {}
ShareGroupContextData::IdHandlerData::~IdHandlerData() = default;

static_assert(gpu::kInvalidResource == 0,
              "GL expects kInvalidResource to be 0");

// The standard id handler.
class IdHandler : public IdHandlerInterface {
 public:
  IdHandler() = default;
  ~IdHandler() override = default;

  // Overridden from IdHandlerInterface.
  void MakeIds(GLES2Implementation* /* gl_impl */,
               GLuint id_offset,
               GLsizei n,
               GLuint* ids) override {
    base::AutoLock auto_lock(lock_);
    if (id_offset == 0) {
      for (GLsizei ii = 0; ii < n; ++ii) {
        ids[ii] = id_allocator_.AllocateID();
      }
    } else {
      for (GLsizei ii = 0; ii < n; ++ii) {
        ids[ii] = id_allocator_.AllocateIDAtOrAbove(id_offset);
        id_offset = ids[ii] + 1;
      }
    }
  }

  // Overridden from IdHandlerInterface.
  bool FreeIds(GLES2Implementation* gl_impl,
               GLsizei n,
               const GLuint* ids,
               DeleteFn delete_fn) override {
    base::AutoLock auto_lock(lock_);

    for (GLsizei ii = 0; ii < n; ++ii) {
      id_allocator_.FreeID(ids[ii]);
    }

    (gl_impl->*delete_fn)(n, ids);
    // We need to ensure that the delete call is evaluated on the service side
    // before any other contexts issue commands using these client ids.
    gl_impl->helper()->CommandBufferHelper::OrderingBarrier();
    return true;
  }

  // Overridden from IdHandlerInterface.
  bool MarkAsUsedForBind(GLES2Implementation* gl_impl,
                         GLenum target,
                         GLuint id,
                         BindFn bind_fn) override {
    base::AutoLock auto_lock(lock_);
    bool result = id ? id_allocator_.MarkAsUsed(id) : true;
    (gl_impl->*bind_fn)(target, id);
    return result;
  }
  bool MarkAsUsedForBind(GLES2Implementation* gl_impl,
                         GLenum target,
                         GLuint index,
                         GLuint id,
                         BindIndexedFn bind_fn) override {
    base::AutoLock auto_lock(lock_);
    bool result = id ? id_allocator_.MarkAsUsed(id) : true;
    (gl_impl->*bind_fn)(target, index, id);
    return result;
  }
  bool MarkAsUsedForBind(GLES2Implementation* gl_impl,
                         GLenum target,
                         GLuint index,
                         GLuint id,
                         GLintptr offset,
                         GLsizeiptr size,
                         BindIndexedRangeFn bind_fn) override {
    base::AutoLock auto_lock(lock_);
    bool result = id ? id_allocator_.MarkAsUsed(id) : true;
    (gl_impl->*bind_fn)(target, index, id, offset, size);
    return result;
  }

  void FreeContext(GLES2Implementation* gl_impl) override {}

 private:
  base::Lock lock_;
  IdAllocator id_allocator_;
};

// An id handler that requires Gen before Bind.
class StrictIdHandler : public IdHandlerInterface {
 public:
  explicit StrictIdHandler(int id_namespace) : id_namespace_(id_namespace) {}
  ~StrictIdHandler() override = default;

  // Overridden from IdHandler.
  void MakeIds(GLES2Implementation* gl_impl,
               GLuint /* id_offset */,
               GLsizei n,
               GLuint* ids) override {
    base::AutoLock auto_lock(lock_);

    // Collect pending FreeIds from other flush_generation.
    CollectPendingFreeIds(gl_impl);

    for (GLsizei ii = 0; ii < n; ++ii) {
      if (!free_ids_.empty()) {
        // Allocate a previously freed Id.
        ids[ii] = free_ids_.top();
        free_ids_.pop();

        // Record kIdInUse state.
        DCHECK(id_states_[ids[ii] - 1] == kIdFree);
        id_states_[ids[ii] - 1] = kIdInUse;
      } else {
        // Allocate a new Id.
        id_states_.push_back(kIdInUse);
        ids[ii] = id_states_.size();
      }
    }
  }

  // Overridden from IdHandler.
  bool FreeIds(GLES2Implementation* gl_impl,
               GLsizei n,
               const GLuint* ids,
               DeleteFn delete_fn) override {
    // Delete stub must run before CollectPendingFreeIds.
    (gl_impl->*delete_fn)(n, ids);

    bool return_value = true;

    {
      base::AutoLock auto_lock(lock_);

      // Collect pending FreeIds from other flush_generation.
      CollectPendingFreeIds(gl_impl);

      // Save Ids to free in a later flush_generation.
      ShareGroupContextData::IdHandlerData* ctxt_data =
          gl_impl->share_group_context_data()->id_handler_data(id_namespace_);

      GLuint max_valid_id = id_states_.size();
      for (GLsizei ii = 0; ii < n; ++ii) {
        GLuint id = ids[ii];
        if (id != 0) {
          if (id > max_valid_id) {
            // Caller will generate an error.
            return_value = false;
            continue;
          }
          // Save freed Id for later.
          if (id_states_[id - 1] != kIdInUse) {
            DVLOG(1) << "Already freed id " << id;
            return_value = false;
            continue;
          }
          id_states_[id - 1] = kIdPendingFree;
          ctxt_data->freed_ids_.push_back(id);
        }
      }
    }

    return return_value;
  }

  // Overridden from IdHandler.
  bool MarkAsUsedForBind(GLES2Implementation* gl_impl,
                         GLenum target,
                         GLuint id,
                         BindFn bind_fn) override {
#ifndef NDEBUG
    if (id != 0) {
      base::AutoLock auto_lock(lock_);
      DCHECK(id_states_[id - 1] == kIdInUse);
    }
#endif
    // StrictIdHandler is used if |bind_generates_resource| is false. In that
    // case, |bind_fn| will not use Flush() after helper->Bind*(), so it is OK
    // to call |bind_fn| without holding the lock.
    (gl_impl->*bind_fn)(target, id);
    return true;
  }
  bool MarkAsUsedForBind(GLES2Implementation* gl_impl,
                         GLenum target,
                         GLuint index,
                         GLuint id,
                         BindIndexedFn bind_fn) override {
#ifndef NDEBUG
    if (id != 0) {
      base::AutoLock auto_lock(lock_);
      DCHECK(id_states_[id - 1] == kIdInUse);
    }
#endif
    // StrictIdHandler is used if |bind_generates_resource| is false. In that
    // case, |bind_fn| will not use Flush() after helper->Bind*(), so it is OK
    // to call |bind_fn| without holding the lock.
    (gl_impl->*bind_fn)(target, index, id);
    return true;
  }
  bool MarkAsUsedForBind(GLES2Implementation* gl_impl,
                         GLenum target,
                         GLuint index,
                         GLuint id,
                         GLintptr offset,
                         GLsizeiptr size,
                         BindIndexedRangeFn bind_fn) override {
#ifndef NDEBUG
    if (id != 0) {
      base::AutoLock auto_lock(lock_);
      DCHECK(id_states_[id - 1] == kIdInUse);
    }
#endif
    // StrictIdHandler is used if |bind_generates_resource| is false. In that
    // case, |bind_fn| will not use Flush() after helper->Bind*(), so it is OK
    // to call |bind_fn| without holding the lock.
    (gl_impl->*bind_fn)(target, index, id, offset, size);
    return true;
  }

  // Overridden from IdHandlerInterface.
  void FreeContext(GLES2Implementation* gl_impl) override {
    base::AutoLock auto_lock(lock_);
    CollectPendingFreeIds(gl_impl);
  }

 private:
  enum IdState { kIdFree, kIdPendingFree, kIdInUse };

  void CollectPendingFreeIds(GLES2Implementation* gl_impl) {
    uint32_t flush_generation = gl_impl->helper()->flush_generation();
    ShareGroupContextData::IdHandlerData* ctxt_data =
        gl_impl->share_group_context_data()->id_handler_data(id_namespace_);

    if (ctxt_data->flush_generation_ != flush_generation) {
      ctxt_data->flush_generation_ = flush_generation;
      for (uint32_t ii = 0; ii < ctxt_data->freed_ids_.size(); ++ii) {
        const GLuint id = ctxt_data->freed_ids_[ii];
        DCHECK(id_states_[id - 1] == kIdPendingFree);
        id_states_[id - 1] = kIdFree;
        free_ids_.push(id);
      }
      ctxt_data->freed_ids_.clear();
    }
  }

  int id_namespace_;

  base::Lock lock_;
  std::vector<uint8_t> id_states_;
  base::stack<uint32_t> free_ids_;
};

// An id handler for ids that are never reused.
class NonReusedIdHandler : public IdHandlerInterface {
 public:
  NonReusedIdHandler() : last_id_(0) {}
  ~NonReusedIdHandler() override = default;

  // Overridden from IdHandlerInterface.
  void MakeIds(GLES2Implementation* /* gl_impl */,
               GLuint id_offset,
               GLsizei n,
               GLuint* ids) override {
    base::AutoLock auto_lock(lock_);
    for (GLsizei ii = 0; ii < n; ++ii) {
      ids[ii] = ++last_id_ + id_offset;
    }
  }

  // Overridden from IdHandlerInterface.
  bool FreeIds(GLES2Implementation* gl_impl,
               GLsizei n,
               const GLuint* ids,
               DeleteFn delete_fn) override {
    // Ids are never freed.
    (gl_impl->*delete_fn)(n, ids);
    return true;
  }

  // Overridden from IdHandlerInterface.
  bool MarkAsUsedForBind(GLES2Implementation* /* gl_impl */,
                         GLenum /* target */,
                         GLuint /* id */,
                         BindFn /* bind_fn */) override {
    // This is only used for Shaders and Programs which have no bind.
    return false;
  }
  bool MarkAsUsedForBind(GLES2Implementation* /* gl_impl */,
                         GLenum /* target */,
                         GLuint /* index */,
                         GLuint /* id */,
                         BindIndexedFn /* bind_fn */) override {
    // This is only used for Shaders and Programs which have no bind.
    return false;
  }
  bool MarkAsUsedForBind(GLES2Implementation* /* gl_impl */,
                         GLenum /* target */,
                         GLuint /* index */,
                         GLuint /* id */,
                         GLintptr /* offset */,
                         GLsizeiptr /* size */,
                         BindIndexedRangeFn /* bind_fn */) override {
    // This is only used for Shaders and Programs which have no bind.
    return false;
  }

  void FreeContext(GLES2Implementation* gl_impl) override {}

 private:
  base::Lock lock_;
  GLuint last_id_;
};

class RangeIdHandler : public RangeIdHandlerInterface {
 public:
  RangeIdHandler() = default;

  void MakeIdRange(GLES2Implementation* /*gl_impl*/,
                   GLsizei n,
                   GLuint* first_id) override {
    base::AutoLock auto_lock(lock_);
    *first_id = id_allocator_.AllocateIDRange(n);
  }

  void FreeIdRange(GLES2Implementation* gl_impl,
                   const GLuint first_id,
                   GLsizei range,
                   DeleteRangeFn delete_fn) override {
    base::AutoLock auto_lock(lock_);
    DCHECK(range > 0);
    id_allocator_.FreeIDRange(first_id, range);
    (gl_impl->*delete_fn)(first_id, range);
    gl_impl->helper()->CommandBufferHelper::OrderingBarrier();
  }

  void FreeContext(GLES2Implementation* gl_impl) override {}

 private:
  base::Lock lock_;
  IdAllocator id_allocator_;
};

ShareGroup::ShareGroup(bool bind_generates_resource, uint64_t tracing_guid)
    : bind_generates_resource_(bind_generates_resource),
      tracing_guid_(tracing_guid) {
  if (bind_generates_resource) {
    for (int i = 0;
         i < static_cast<int>(SharedIdNamespaces::kNumSharedIdNamespaces);
         ++i) {
      if (i == static_cast<int>(SharedIdNamespaces::kProgramsAndShaders)) {
        id_handlers_[i].reset(new NonReusedIdHandler());
      } else {
        id_handlers_[i].reset(new IdHandler());
      }
    }
  } else {
    for (int i = 0;
         i < static_cast<int>(SharedIdNamespaces::kNumSharedIdNamespaces);
         ++i) {
      if (i == static_cast<int>(SharedIdNamespaces::kProgramsAndShaders)) {
        id_handlers_[i].reset(new NonReusedIdHandler());
      } else {
        id_handlers_[i].reset(new StrictIdHandler(i));
      }
    }
  }
  program_info_manager_.reset(new ProgramInfoManager);
  for (auto& range_id_handler : range_id_handlers_) {
    range_id_handler.reset(new RangeIdHandler());
  }
}

void ShareGroup::Lose() {
  base::AutoLock hold(lost_lock_);
  lost_ = true;
}

bool ShareGroup::IsLost() const {
  base::AutoLock hold(lost_lock_);
  return lost_;
}

void ShareGroup::SetProgramInfoManagerForTesting(ProgramInfoManager* manager) {
  program_info_manager_.reset(manager);
}

ShareGroup::~ShareGroup() = default;

}  // namespace gles2
}  // namespace gpu
