// 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 <stack>
#include <vector>
#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() {}

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

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

  // 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 {}

  // 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);

    {
      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_);

      for (GLsizei ii = 0; ii < n; ++ii) {
        GLuint id = ids[ii];
        if (id != 0) {
          // Save freed Id for later.
          DCHECK(id_states_[id - 1] == kIdInUse);
          id_states_[id - 1] = kIdPendingFree;
          ctxt_data->freed_ids_.push_back(id);
        }
      }
    }

    return true;
  }

  // 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_;
  std::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 {}

  // 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() {}

  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 < id_namespaces::kNumIdNamespaces; ++i) {
      if (i == id_namespaces::kProgramsAndShaders) {
        id_handlers_[i].reset(new NonReusedIdHandler());
      } else {
        id_handlers_[i].reset(new IdHandler());
      }
    }
  } else {
    for (int i = 0; i < id_namespaces::kNumIdNamespaces; ++i) {
      if (i == id_namespaces::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() {}

}  // namespace gles2
}  // namespace gpu
