// 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 <deque>
#include <vector>
#include "base/atomicops.h"
#include "base/basictypes.h"
#include "base/containers/hash_tables.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "gpu/command_buffer/service/feature_info.h"
#include "gpu/gpu_export.h"

namespace gpu {

class GLES2Decoder;

namespace gles2 {

class FeatureInfo;

// This class keeps track of the queries and their state
// As Queries are not shared there is one QueryManager per context.
class GPU_EXPORT QueryManager {
 public:
  class GPU_EXPORT Query : public base::RefCounted<Query> {
   public:
    Query(
        QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset);

    GLenum target() const {
      return target_;
    }

    bool IsDeleted() const {
      return deleted_;
    }

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

    bool pending() const {
      return pending_;
    }

    int32 shm_id() const {
      return shm_id_;
    }

    uint32 shm_offset() const {
      return shm_offset_;
    }

    // Returns false if shared memory for sync is invalid.
    virtual bool Begin() = 0;

    // Returns false if shared memory for sync is invalid.
    virtual bool End(base::subtle::Atomic32 submit_count) = 0;

    // Returns false if shared memory for sync is invalid.
    virtual bool Process() = 0;

    virtual void Destroy(bool have_context) = 0;

    void AddCallback(base::Closure callback);

   protected:
    virtual ~Query();

    QueryManager* manager() const {
      return manager_;
    }

    void MarkAsDeleted() {
      deleted_ = true;
    }

    // Returns false if shared memory for sync is invalid.
    bool MarkAsCompleted(uint64 result);

    void MarkAsPending(base::subtle::Atomic32 submit_count) {
      DCHECK(!pending_);
      pending_ = true;
      submit_count_ = submit_count;
    }

    void UnmarkAsPending() {
      DCHECK(pending_);
      pending_ = false;
    }

    // Returns false if shared memory for sync is invalid.
    bool AddToPendingQueue(base::subtle::Atomic32 submit_count) {
      return manager_->AddPendingQuery(this, submit_count);
    }

    // Returns false if shared memory for sync is invalid.
    bool AddToPendingTransferQueue(base::subtle::Atomic32 submit_count) {
      return manager_->AddPendingTransferQuery(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.
    int32 shm_id_;
    uint32 shm_offset_;

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

    // True if in the queue.
    bool pending_;

    // True if deleted.
    bool deleted_;

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

  QueryManager(
      GLES2Decoder* decoder,
      FeatureInfo* feature_info);
  ~QueryManager();

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

  // Creates a Query for the given query.
  Query* CreateQuery(
      GLenum target, GLuint client_id, int32 shm_id, uint32 shm_offset);

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

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

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

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

  // Processes pending queries. Returns false if any queries are pointing
  // to invalid shared memory.
  bool ProcessPendingQueries();

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

  // Processes pending transfer queries. Returns false if any queries are
  // pointing to invalid shared memory.
  bool ProcessPendingTransferQueries();

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

  GLES2Decoder* decoder() const {
    return decoder_;
  }

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

 private:
  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.
  bool AddPendingQuery(Query* query, base::subtle::Atomic32 submit_count);

  // Adds to queue of transfer queries waiting for completion.
  // Returns false if any query is pointing to invalid shared memory.
  bool AddPendingTransferQuery(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.
  bool RemovePendingQuery(Query* query);

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

  // Used to validate shared memory and get GL errors.
  GLES2Decoder* decoder_;

  bool use_arb_occlusion_query2_for_occlusion_query_boolean_;
  bool use_arb_occlusion_query_for_occlusion_query_boolean_;

  // 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.
  typedef base::hash_map<GLuint, scoped_refptr<Query> > QueryMap;
  QueryMap queries_;

  typedef base::hash_set<GLuint> GeneratedQueryIds;
  GeneratedQueryIds generated_query_ids_;

  // Queries waiting for completion.
  typedef std::deque<scoped_refptr<Query> > QueryQueue;
  QueryQueue pending_queries_;

  // Async pixel transfer queries waiting for completion.
  QueryQueue pending_transfer_queries_;

  DISALLOW_COPY_AND_ASSIGN(QueryManager);
};

}  // namespace gles2
}  // namespace gpu

#endif  // GPU_COMMAND_BUFFER_SERVICE_QUERY_MANAGER_H_
