// 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.

#ifndef GPU_COMMAND_BUFFER_SERVICE_BUFFER_MANAGER_H_
#define GPU_COMMAND_BUFFER_SERVICE_BUFFER_MANAGER_H_

#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>

#include <map>
#include <memory>
#include <unordered_map>
#include <vector>

#include "base/check_op.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/trace_event/memory_dump_provider.h"
#include "gpu/command_buffer/common/buffer.h"
#include "gpu/command_buffer/service/gl_utils.h"
#include "gpu/command_buffer/service/memory_tracking.h"
#include "gpu/gpu_gles2_export.h"

namespace gpu {
namespace gles2 {

class BufferManager;
struct ContextState;
class ErrorState;
class FeatureInfo;
class IndexedBufferBindingHost;
class TestHelper;

// Info about Buffers currently in the system.
class GPU_GLES2_EXPORT Buffer : public base::RefCounted<Buffer> {
 public:
  struct MappedRange {
    GLintptr offset;
    GLsizeiptr size;
    GLenum access;
    void* pointer;  // Pointer returned by driver.
    scoped_refptr<gpu::Buffer> shm;  // Client side mem buffer.
    unsigned int shm_offset;  // Client side mem buffer offset.

    MappedRange(GLintptr offset, GLsizeiptr size, GLenum access, void* pointer,
                scoped_refptr<gpu::Buffer> shm, unsigned int shm_offset);
    ~MappedRange();
    void* GetShmPointer() const;
  };

  Buffer(BufferManager* manager, GLuint service_id);

  GLenum initial_target() const { return initial_target_; }

  GLuint service_id() const {
    return service_id_;
  }

  GLsizeiptr size() const {
    return size_;
  }

  GLenum usage() const {
    return usage_;
  }

  bool shadowed() const {
    return !shadow_.empty();
  }

  // Gets the maximum value in the buffer for the given range interpreted as
  // the given type. Returns false if offset and count are out of range.
  // offset is in bytes.
  // count is in elements of type.
  bool GetMaxValueForRange(GLuint offset, GLsizei count, GLenum type,
                           bool primitive_restart_enabled, GLuint* max_value);

  // Returns a pointer to shadowed data.
  const void* GetRange(GLintptr offset, GLsizeiptr size) const;

  // Check if an offset, size range is valid for the current buffer.
  bool CheckRange(GLintptr offset, GLsizeiptr size) const;

  // Sets a range of this buffer's shadowed data.
  void SetRange(GLintptr offset, GLsizeiptr size, const GLvoid * data);

  bool IsDeleted() const {
    return deleted_;
  }

  bool IsValid() const {
    return initial_target() && !IsDeleted();
  }

  bool IsClientSideArray() const {
    return is_client_side_array_;
  }

  void SetMappedRange(GLintptr offset, GLsizeiptr size, GLenum access,
                      void* pointer, scoped_refptr<gpu::Buffer> shm,
                      unsigned int shm_offset);
  void RemoveMappedRange();
  const MappedRange* GetMappedRange() const {
    return mapped_range_.get();
  }

  // These maintain the reference counts for checking whether a buffer is
  // double-bound to transform feedback and non-transform-feedback binding
  // points.
  void OnBind(GLenum target, bool indexed);
  void OnUnbind(GLenum target, bool indexed);

  bool IsBoundForTransformFeedbackAndOther() const {
    return transform_feedback_indexed_binding_count_ > 0 &&
           non_transform_feedback_binding_count_ > 0;
  }

  bool IsDoubleBoundForTransformFeedback() const {
    return transform_feedback_indexed_binding_count_ > 1;
  }

  void SetReadbackShadowAllocation(scoped_refptr<gpu::Buffer> shm,
                                   uint32_t shm_offset);
  scoped_refptr<gpu::Buffer> TakeReadbackShadowAllocation(void** data);

 private:
  friend class BufferManager;
  friend class BufferManagerTestBase;
  friend class base::RefCounted<Buffer>;

  // Represents a range in a buffer.
  class Range {
   public:
    Range(GLuint offset, GLsizei count, GLenum type,
          bool primitive_restart_enabled)
        : offset_(offset),
          count_(count),
          type_(type),
          primitive_restart_enabled_(primitive_restart_enabled) {
    }

    // A less functor provided for std::map so it can find ranges.
    struct Less {
      bool operator() (const Range& lhs, const Range& rhs) const {
        if (lhs.offset_ != rhs.offset_) {
          return lhs.offset_ < rhs.offset_;
        }
        if (lhs.count_ != rhs.count_) {
          return lhs.count_ < rhs.count_;
        }
        if (lhs.type_ != rhs.type_) {
          return lhs.type_ < rhs.type_;
        }
        return lhs.primitive_restart_enabled_ < rhs.primitive_restart_enabled_;
      }
    };

   private:
    GLuint offset_;
    GLsizei count_;
    GLenum type_;
    bool primitive_restart_enabled_;
  };

  ~Buffer();

  void set_initial_target(GLenum target) {
    DCHECK_EQ(0u, initial_target_);
    initial_target_ = target;
  }

  void MarkAsDeleted() {
    deleted_ = true;
  }

  // Setup the shadow buffer. This will either initialize the shadow buffer
  // with the passed data or clear the shadow buffer if no shadow required. This
  // will return a pointer to the shadowed data if using shadow, otherwise will
  // return the original data pointer.
  const GLvoid* StageShadow(bool use_shadow,
                            GLsizeiptr size,
                            const GLvoid* data);

  // Sets the size, usage and initial data of a buffer.
  // If shadow is true then if data is NULL buffer will be initialized to 0.
  void SetInfo(GLsizeiptr size,
               GLenum usage,
               bool use_shadow,
               bool is_client_side_array);

  // Clears any cache of index ranges.
  void ClearCache();

  // The manager that owns this Buffer.
  BufferManager* manager_;

  // A copy of the data in the buffer. This data is only kept if the conditions
  // checked in UseShadowBuffer() are true.
  std::vector<uint8_t> shadow_;

  // Size of buffer.
  GLsizeiptr size_;

  // True if deleted.
  bool deleted_;

  // Whether or not this Buffer is not uploaded to the GPU but just
  // sitting in local memory.
  bool is_client_side_array_;

  // Keeps track of whether this buffer is currently bound for transform
  // feedback in a WebGL context. Used as an optimization when validating WebGL
  // draw calls for compliance with binding restrictions.
  // http://crbug.com/696345
  int non_transform_feedback_binding_count_ = 0;
  int transform_feedback_indexed_binding_count_ = 0;

  // Service side buffer id.
  GLuint service_id_;

  // The first target of buffer. 0 = unset.
  // It is set the first time bindBuffer() is called and cannot be changed.
  GLenum initial_target_;

  // Usage of buffer.
  GLenum usage_;

  // Data cached from last glMapBufferRange call.
  std::unique_ptr<MappedRange> mapped_range_;

  // A map of ranges to the highest value in that range of a certain type.
  typedef std::map<Range, GLuint, Range::Less> RangeToMaxValueMap;
  RangeToMaxValueMap range_set_;

  scoped_refptr<gpu::Buffer> readback_shm_;
  uint32_t readback_shm_offset_ = 0;
};

// This class keeps track of the buffers and their sizes so we can do
// bounds checking.
//
// NOTE: To support shared resources an instance of this class will need to be
// shared by multiple GLES2Decoders.
class GPU_GLES2_EXPORT BufferManager
    : public base::trace_event::MemoryDumpProvider {
 public:
  BufferManager(MemoryTracker* memory_tracker, FeatureInfo* feature_info);
  ~BufferManager() override;

  void MarkContextLost();

  // Must call before destruction.
  void Destroy();

  // Creates a Buffer for the given buffer.
  void CreateBuffer(GLuint client_id, GLuint service_id);

  // Gets the buffer info for the given buffer.
  Buffer* GetBuffer(GLuint client_id);

  // Removes a buffer info for the given buffer.
  void RemoveBuffer(GLuint client_id);

  // Gets a client id for a given service id.
  bool GetClientId(GLuint service_id, GLuint* client_id) const;

  // Validates a glBufferSubData, and then calls DoBufferData if validation was
  // successful.
  void ValidateAndDoBufferSubData(ContextState* context_state,
                                  ErrorState* error_state,
                                  GLenum target,
                                  GLintptr offset,
                                  GLsizeiptr size,
                                  const GLvoid* data);

  // Validates a glBufferData, and then calls DoBufferData if validation was
  // successful.
  void ValidateAndDoBufferData(ContextState* context_state,
                               ErrorState* error_state,
                               GLenum target,
                               GLsizeiptr size,
                               const GLvoid* data,
                               GLenum usage);

  // Validates a glCopyBufferSubData, and then calls DoCopyBufferSubData if
  // validation was successful.
  void ValidateAndDoCopyBufferSubData(ContextState* context_state,
                                      ErrorState* error_state,
                                      GLenum readtarget,
                                      GLenum writetarget,
                                      GLintptr readoffset,
                                      GLintptr writeoffset,
                                      GLsizeiptr size);

  // Validates a glGetBufferParameteri64v, and then calls GetBufferParameteri64v
  // if validation was successful.
  void ValidateAndDoGetBufferParameteri64v(ContextState* context_state,
                                           ErrorState* error_state,
                                           GLenum target,
                                           GLenum pname,
                                           GLint64* params);

  // Validates a glGetBufferParameteriv, and then calls GetBufferParameteriv if
  // validation was successful.
  void ValidateAndDoGetBufferParameteriv(ContextState* context_state,
                                         ErrorState* error_state,
                                         GLenum target,
                                         GLenum pname,
                                         GLint* params);

  // Sets the target of a buffer. Returns false if the target can not be set.
  bool SetTarget(Buffer* buffer, GLenum target);

  void set_max_buffer_size(GLsizeiptr max_buffer_size) {
    max_buffer_size_ = max_buffer_size;
  }

  void set_allow_buffers_on_multiple_targets(bool allow) {
    allow_buffers_on_multiple_targets_ = allow;
  }

  void set_allow_fixed_attribs(bool allow) {
    allow_fixed_attribs_ = allow;
  }

  size_t mem_represented() const {
    return memory_type_tracker_->GetMemRepresented();
  }

  // Tells for a given usage if this would be a client side array.
  bool IsUsageClientSideArray(GLenum usage);

  // Tells whether a buffer that is emulated using client-side arrays should be
  // set to a non-zero size.
  bool UseNonZeroSizeForClientSideArrayBuffer();

  void SetPrimitiveRestartFixedIndexIfNecessary(GLenum type);

  Buffer* GetBufferInfoForTarget(ContextState* state, GLenum target) const;

  // base::trace_event::MemoryDumpProvider implementation.
  bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
                    base::trace_event::ProcessMemoryDump* pmd) override;

  // Validate if a buffer is bound at target, if it's unmapped, if it's
  // large enough. Return the buffer bound to |target| if access is granted;
  // return nullptr if a GL error is generated.
  // Generates INVALID_VALUE if offset + size is out of range.
  Buffer* RequestBufferAccess(ContextState* context_state,
                              ErrorState* error_state,
                              GLenum target,
                              GLintptr offset,
                              GLsizeiptr size,
                              const char* func_name);
  // Same as above, but assume to access the entire buffer.
  Buffer* RequestBufferAccess(ContextState* context_state,
                              ErrorState* error_state,
                              GLenum target,
                              const char* func_name);
  // Same as above, but it can be any buffer rather than the buffer bound to
  // |target|. Return true if access is granted; return false if a GL error is
  // generated.
  bool RequestBufferAccess(ErrorState* error_state,
                           Buffer* buffer,
                           const char* func_name,
                           const char* error_message_format,
                           ...);
  // Generates INVALID_OPERATION if offset + size is out of range.
  bool RequestBufferAccess(ErrorState* error_state,
                           Buffer* buffer,
                           GLintptr offset,
                           GLsizeiptr size,
                           const char* func_name,
                           const char* error_message);
  // Returns false and generates INVALID_OPERATION if buffer at binding |ii|
  // doesn't exist, is mapped, or smaller than |variable_sizes[ii]| * |count|.
  // Return true otherwise.
  bool RequestBuffersAccess(ErrorState* error_state,
                            const IndexedBufferBindingHost* bindings,
                            const std::vector<GLsizeiptr>& variable_sizes,
                            GLsizei count,
                            const char* func_name,
                            const char* message_tag);

 private:
  friend class Buffer;
  friend class TestHelper;  // Needs access to DoBufferData.
  friend class BufferManagerTestBase;  // Needs access to DoBufferSubData.
  friend class IndexedBufferBindingHostTest;  // Needs access to SetInfo.

  void StartTracking(Buffer* buffer);
  void StopTracking(Buffer* buffer);

  // Does a glBufferSubData and updates the appropriate accounting.
  // Assumes the values have already been validated.
  void DoBufferSubData(
      Buffer* buffer,
      GLenum target,
      GLintptr offset,
      GLsizeiptr size,
      const GLvoid* data);

  // Does a glBufferData and updates the appropriate accounting.
  // Assumes the values have already been validated.
  void DoBufferData(
      ErrorState* error_state,
      Buffer* buffer,
      GLenum target,
      GLsizeiptr size,
      GLenum usage,
      const GLvoid* data);

  // Does a glCopyBufferSubData and updates the appropriate accounting.
  // Assumes the values have already been validated.
  void DoCopyBufferSubData(
      Buffer* readbuffer,
      GLenum readtarget,
      GLintptr readoffset,
      Buffer* writebuffer,
      GLenum writetarget,
      GLintptr writeoffset,
      GLsizeiptr size);

  // Tests whether a shadow buffer needs to be used.
  bool UseShadowBuffer(GLenum target, GLenum usage);

  // Sets the size, usage and initial data of a buffer.
  // If data is NULL buffer will be initialized to 0 if shadowed.
  void SetInfo(Buffer* buffer,
               GLenum target,
               GLsizeiptr size,
               GLenum usage,
               bool use_shadow);

  // Same as public RequestBufferAccess taking similar arguments, but
  // allows caller to assemble the va_list.
  bool RequestBufferAccessV(ErrorState* error_state,
                            Buffer* buffer,
                            const char* func_name,
                            const char* error_message_format,
                            va_list varargs);

  std::unique_ptr<MemoryTypeTracker> memory_type_tracker_;
  MemoryTracker* memory_tracker_;
  scoped_refptr<FeatureInfo> feature_info_;

  // Info for each buffer in the system.
  typedef std::unordered_map<GLuint, scoped_refptr<Buffer>> BufferMap;
  BufferMap buffers_;

  // The maximum size of buffers.
  GLsizeiptr max_buffer_size_;

  // Whether or not buffers can be bound to multiple targets.
  bool allow_buffers_on_multiple_targets_;

  // Whether or not allow using GL_FIXED type for vertex attribs.
  bool allow_fixed_attribs_;

  // Counts the number of Buffer allocated with 'this' as its manager.
  // Allows to check no Buffer will outlive this.
  unsigned int buffer_count_;

  GLuint primitive_restart_fixed_index_;

  bool lost_context_;
  bool use_client_side_arrays_for_stream_buffers_;

  DISALLOW_COPY_AND_ASSIGN(BufferManager);
};

}  // namespace gles2
}  // namespace gpu

#endif  // GPU_COMMAND_BUFFER_SERVICE_BUFFER_MANAGER_H_
