// 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/query_tracker.h"

#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <GLES2/gl2extchromium.h>

#include "base/atomicops.h"
#include "gpu/command_buffer/client/gles2_cmd_helper.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "gpu/command_buffer/client/mapped_memory.h"
#include "gpu/command_buffer/common/time.h"

namespace gpu {
namespace gles2 {

QuerySyncManager::QuerySyncManager(MappedMemoryManager* manager)
    : mapped_memory_(manager) {
  DCHECK(manager);
}

QuerySyncManager::~QuerySyncManager() {
  while (!buckets_.empty()) {
    mapped_memory_->Free(buckets_.front()->syncs);
    delete buckets_.front();
    buckets_.pop_front();
  }
}

bool QuerySyncManager::Alloc(QuerySyncManager::QueryInfo* info) {
  DCHECK(info);
  if (free_queries_.empty()) {
    int32 shm_id;
    unsigned int shm_offset;
    void* mem = mapped_memory_->Alloc(
        kSyncsPerBucket * sizeof(QuerySync), &shm_id, &shm_offset);
    if (!mem) {
      return false;
    }
    QuerySync* syncs = static_cast<QuerySync*>(mem);
    Bucket* bucket = new Bucket(syncs);
    buckets_.push_back(bucket);
    for (size_t ii = 0; ii < kSyncsPerBucket; ++ii) {
      free_queries_.push_back(QueryInfo(bucket, shm_id, shm_offset, syncs));
      ++syncs;
      shm_offset += sizeof(*syncs);
    }
  }
  *info = free_queries_.front();
  ++(info->bucket->used_query_count);
  info->sync->Reset();
  free_queries_.pop_front();
  return true;
}

void QuerySyncManager::Free(const QuerySyncManager::QueryInfo& info) {
  DCHECK_GT(info.bucket->used_query_count, 0u);
  --(info.bucket->used_query_count);
  free_queries_.push_back(info);
}

void QuerySyncManager::Shrink() {
  std::deque<QueryInfo> new_queue;
  while (!free_queries_.empty()) {
    if (free_queries_.front().bucket->used_query_count)
      new_queue.push_back(free_queries_.front());
    free_queries_.pop_front();
  }
  free_queries_.swap(new_queue);

  std::deque<Bucket*> new_buckets;
  while (!buckets_.empty()) {
    Bucket* bucket = buckets_.front();
    if (bucket->used_query_count) {
      new_buckets.push_back(bucket);
    } else {
      mapped_memory_->Free(bucket->syncs);
      delete bucket;
    }
    buckets_.pop_front();
  }
  buckets_.swap(new_buckets);
}

QueryTracker::Query::Query(GLuint id, GLenum target,
                           const QuerySyncManager::QueryInfo& info)
    : id_(id),
      target_(target),
      info_(info),
      state_(kUninitialized),
      submit_count_(0),
      token_(0),
      flush_count_(0),
      client_begin_time_us_(0),
      result_(0) {
    }


void QueryTracker::Query::Begin(GLES2Implementation* gl) {
  // init memory, inc count
  MarkAsActive();

  switch (target()) {
    case GL_GET_ERROR_QUERY_CHROMIUM:
      // To nothing on begin for error queries.
      break;
    case GL_LATENCY_QUERY_CHROMIUM:
      client_begin_time_us_ = MicrosecondsSinceOriginOfTime();
      // tell service about id, shared memory and count
      gl->helper()->BeginQueryEXT(target(), id(), shm_id(), shm_offset());
      break;
    case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
    case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
    default:
      // tell service about id, shared memory and count
      gl->helper()->BeginQueryEXT(target(), id(), shm_id(), shm_offset());
      break;
  }
}

void QueryTracker::Query::End(GLES2Implementation* gl) {
  switch (target()) {
    case GL_GET_ERROR_QUERY_CHROMIUM: {
      GLenum error = gl->GetClientSideGLError();
      if (error == GL_NO_ERROR) {
        // There was no error so start the query on the service.
        // it will end immediately.
        gl->helper()->BeginQueryEXT(target(), id(), shm_id(), shm_offset());
      } else {
        // There's an error on the client, no need to bother the service. Just
        // set the query as completed and return the error.
        if (error != GL_NO_ERROR) {
          state_ = kComplete;
          result_ = error;
          return;
        }
      }
    }
  }
  flush_count_ = gl->helper()->flush_generation();
  gl->helper()->EndQueryEXT(target(), submit_count());
  MarkAsPending(gl->helper()->InsertToken());
}

bool QueryTracker::Query::CheckResultsAvailable(
    CommandBufferHelper* helper) {
  if (Pending()) {
    if (base::subtle::Acquire_Load(&info_.sync->process_count) ==
            submit_count_ ||
        helper->IsContextLost()) {
      switch (target()) {
        case GL_COMMANDS_ISSUED_CHROMIUM:
          result_ = std::min(info_.sync->result,
                             static_cast<uint64>(0xFFFFFFFFL));
          break;
        case GL_LATENCY_QUERY_CHROMIUM:
          // Disabled DCHECK because of http://crbug.com/419236.
          //DCHECK(info_.sync->result >= client_begin_time_us_);
          result_ = std::min(info_.sync->result - client_begin_time_us_,
                             static_cast<uint64>(0xFFFFFFFFL));
          break;
        case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
        case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
        default:
          result_ = info_.sync->result;
          break;
      }
      state_ = kComplete;
    } else {
      if ((helper->flush_generation() - flush_count_ - 1) >= 0x80000000) {
        helper->Flush();
      } else {
        // Insert no-ops so that eventually the GPU process will see more work.
        helper->Noop(1);
      }
    }
  }
  return state_ == kComplete;
}

uint32 QueryTracker::Query::GetResult() const {
  DCHECK(state_ == kComplete || state_ == kUninitialized);
  return result_;
}

QueryTracker::QueryTracker(MappedMemoryManager* manager)
    : query_sync_manager_(manager) {
}

QueryTracker::~QueryTracker() {
  while (!queries_.empty()) {
    delete queries_.begin()->second;
    queries_.erase(queries_.begin());
  }
  while (!removed_queries_.empty()) {
    delete removed_queries_.front();
    removed_queries_.pop_front();
  }
}

QueryTracker::Query* QueryTracker::CreateQuery(GLuint id, GLenum target) {
  DCHECK_NE(0u, id);
  FreeCompletedQueries();
  QuerySyncManager::QueryInfo info;
  if (!query_sync_manager_.Alloc(&info)) {
    return NULL;
  }
  Query* query = new Query(id, target, info);
  std::pair<QueryMap::iterator, bool> result =
      queries_.insert(std::make_pair(id, query));
  DCHECK(result.second);
  return query;
}

QueryTracker::Query* QueryTracker::GetQuery(
    GLuint client_id) {
  QueryMap::iterator it = queries_.find(client_id);
  return it != queries_.end() ? it->second : NULL;
}

void QueryTracker::RemoveQuery(GLuint client_id) {
  QueryMap::iterator it = queries_.find(client_id);
  if (it != queries_.end()) {
    Query* query = it->second;
    // When you delete a query you can't mark its memory as unused until it's
    // completed.
    // Note: If you don't do this you won't mess up the service but you will
    // mess up yourself.
    removed_queries_.push_back(query);
    queries_.erase(it);
    FreeCompletedQueries();
  }
}

void QueryTracker::Shrink() {
  FreeCompletedQueries();
  query_sync_manager_.Shrink();
}

void QueryTracker::FreeCompletedQueries() {
  QueryList::iterator it = removed_queries_.begin();
  while (it != removed_queries_.end()) {
    Query* query = *it;
    if (query->Pending() &&
        base::subtle::Acquire_Load(&query->info_.sync->process_count) !=
            query->submit_count()) {
      ++it;
      continue;
    }

    query_sync_manager_.Free(query->info_);
    it = removed_queries_.erase(it);
    delete query;
  }
}

}  // namespace gles2
}  // namespace gpu
