// 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_QUERY_MANAGER_H_
#define GPU_COMMAND_BUFFER_SERVICE_QUERY_MANAGER_H_

#include <stdint.h>

#include <memory>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include "base/atomicops.h"
#include "base/callback_forward.h"
#include "base/containers/circular_deque.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "gpu/command_buffer/common/buffer.h"
#include "gpu/command_buffer/common/common_cmd_format.h"
#include "gpu/command_buffer/common/gl2_types.h"
#include "gpu/gpu_gles2_export.h"

namespace gpu {

// This class keeps track of the queries and their state
// As Queries are not shared there is one QueryManager per context.
class GPU_GLES2_EXPORT QueryManager {
 public:
  class GPU_GLES2_EXPORT Query : public base::RefCounted<Query> {
   public:
    Query(QueryManager* manager,
          GLenum target,
          scoped_refptr<gpu::Buffer> buffer,
          QuerySync* sync);

    GLenum target() const {
      return target_;
    }

    bool IsDeleted() const {
      return deleted_;
    }

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

    bool IsActive() const {
      return query_state_ == kQueryState_Active;
    }

    bool IsPaused() const {
      return query_state_ == kQueryState_Paused;
    }

    bool IsPending() const {
      return query_state_ == kQueryState_Pending;
    }

    bool IsFinished() const {
      return query_state_ == kQueryState_Finished;
    }

    const QuerySync* sync() const { return sync_; }

    virtual void Begin() = 0;

    virtual void End(base::subtle::Atomic32 submit_count) = 0;

    virtual void QueryCounter(base::subtle::Atomic32 submit_count) = 0;

    virtual void Process(bool did_finish) = 0;

    // Pauses active query to be resumed later.
    virtual void Pause() = 0;

    // Resume from a paused active query.
    virtual void Resume() = 0;

    virtual void Destroy(bool have_context) = 0;

    virtual void BeginProcessingCommands() {}
    virtual void EndProcessingCommands() {}

    void AddCallback(base::OnceClosure callback);

   protected:
    virtual ~Query();

    QueryManager* manager() const {
      return manager_;
    }

    void MarkAsDeleted() {
      deleted_ = true;
    }

    void MarkAsActive() {
      DCHECK(query_state_ == kQueryState_Initialize ||
             query_state_ == kQueryState_Paused ||
             query_state_ == kQueryState_Finished);
      query_state_ = kQueryState_Active;
    }

    void MarkAsPaused() {
      DCHECK(query_state_ == kQueryState_Active);
      query_state_ = kQueryState_Paused;
    }

    void MarkAsPending(base::subtle::Atomic32 submit_count) {
      DCHECK(query_state_ == kQueryState_Active);
      query_state_ = kQueryState_Pending;
      submit_count_ = submit_count;
    }

    void MarkAsCompleted(uint64_t result);

    void UnmarkAsPending() {
      DCHECK(query_state_ == kQueryState_Pending);
      query_state_ = kQueryState_Finished;
    }

    void AddToPendingQueue(base::subtle::Atomic32 submit_count) {
      manager_->AddPendingQuery(this, submit_count);
    }

    void BeginQueryHelper(GLenum target, GLuint id) {
      manager_->BeginQueryHelper(target, id);
    }

    void EndQueryHelper(GLenum target) {
      manager_->EndQueryHelper(target);
    }

    base::subtle::Atomic32 submit_count() const { return submit_count_; }

   private:
    friend class QueryManager;
    friend class QueryManagerTest;
    friend class base::RefCounted<Query>;

    void RunCallbacks();

    // The manager that owns this Query.
    QueryManager* manager_;

    // The type of query.
    GLenum target_;

    // The shared memory used with this Query. We keep a reference to the Buffer
    // to ensure it doesn't get released until we wrote results. sync_ points to
    // memory inside buffer_.
    scoped_refptr<gpu::Buffer> buffer_;
    QuerySync* sync_;

    // Count to set process count do when completed.
    base::subtle::Atomic32 submit_count_;

    // Current state of the query.
    enum QueryState {
      kQueryState_Initialize, // Has not been queried yet.
      kQueryState_Active, // Query began but has not ended.
      kQueryState_Paused, // Query was active but is now paused.
      kQueryState_Pending, // Query ended, waiting for result.
      kQueryState_Finished, // Query received result.
    } query_state_;

    // True if deleted.
    bool deleted_;

    // List of callbacks to run when result is available.
    std::vector<base::OnceClosure> callbacks_;
  };

  QueryManager();
  virtual ~QueryManager();

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

  // Creates a Query for the given query.
  virtual Query* CreateQuery(GLenum target,
                             GLuint client_id,
                             scoped_refptr<gpu::Buffer> buffer,
                             QuerySync* sync);

  // Gets the query info for the given query.
  Query* GetQuery(GLuint client_id);

  // Gets the currently active query for a target.
  Query* GetActiveQuery(GLenum target);

  // Removes a query info for the given query.
  void RemoveQuery(GLuint client_id);

  // Returns false if any query is pointing to invalid shared memory.
  void BeginQuery(Query* query);

  // Returns false if any query is pointing to invalid shared memory.
  void EndQuery(Query* query, base::subtle::Atomic32 submit_count);

  // Returns false if any query is pointing to invalid shared memory.
  void QueryCounter(Query* query, base::subtle::Atomic32 submit_count);

  void PauseQueries();
  void ResumeQueries();

  void BeginProcessingCommands();
  void EndProcessingCommands();

  // Processes pending queries. Returns false if any queries are pointing
  // to invalid shared memory. |did_finish| is true if this is called as
  // a result of calling glFinish().
  void ProcessPendingQueries(bool did_finish);

  // True if there are pending queries.
  bool HavePendingQueries();

  void GenQueries(GLsizei n, const GLuint* queries);
  bool IsValidQuery(GLuint id);

 protected:
  void StartTracking(Query* query);
  void StopTracking(Query* query);

  // Wrappers for BeginQueryARB and EndQueryARB to hide differences between
  // ARB_occlusion_query2 and EXT_occlusion_query_boolean.
  void BeginQueryHelper(GLenum target, GLuint id);
  void EndQueryHelper(GLenum target);

  // Adds to queue of queries waiting for completion.
  // Returns false if any query is pointing to invalid shared memory.
  void AddPendingQuery(Query* query, base::subtle::Atomic32 submit_count);

  // Removes a query from the queue of pending queries.
  // Returns false if any query is pointing to invalid shared memory.
  void RemovePendingQuery(Query* query);

  // Returns a target used for the underlying GL extension
  // used to emulate a query.
  virtual GLenum AdjustTargetForEmulation(GLenum target);

  // Counts the number of Queries allocated with 'this' as their manager.
  // Allows checking no Query will outlive this.
  unsigned query_count_;

  // Info for each query in the system.
  using QueryMap = std::unordered_map<GLuint, scoped_refptr<Query>>;
  QueryMap queries_;

  using GeneratedQueryIds = std::unordered_set<GLuint>;
  GeneratedQueryIds generated_query_ids_;

  // A map of targets -> Query for current active queries.
  using ActiveQueryMap = std::map<GLenum, scoped_refptr<Query>>;
  ActiveQueryMap active_queries_;

  // Queries waiting for completion.
  using QueryQueue = base::circular_deque<scoped_refptr<Query>>;
  QueryQueue pending_queries_;

  DISALLOW_COPY_AND_ASSIGN(QueryManager);
};

}  // namespace gpu

#endif  // GPU_COMMAND_BUFFER_SERVICE_QUERY_MANAGER_H_
