// Copyright (c) 2013 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/service/error_state.h"

#include <stdint.h>

#include <string>

#include "base/macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "gpu/command_buffer/common/gles2_cmd_utils.h"
#include "gpu/command_buffer/service/logger.h"
#include "ui/gl/gl_bindings.h"

namespace gpu {
namespace gles2 {

class ErrorStateImpl : public ErrorState {
 public:
  explicit ErrorStateImpl(ErrorStateClient* client, Logger* logger);
  ~ErrorStateImpl() override;

  uint32_t GetGLError() override;

  void SetGLError(const char* filename,
                  int line,
                  unsigned int error,
                  const char* function_name,
                  const char* msg) override;
  void SetGLErrorInvalidEnum(const char* filename,
                             int line,
                             const char* function_name,
                             unsigned int value,
                             const char* label) override;
  void SetGLErrorInvalidParami(const char* filename,
                               int line,
                               unsigned int error,
                               const char* function_name,
                               unsigned int pname,
                               int param) override;
  void SetGLErrorInvalidParamf(const char* filename,
                               int line,
                               unsigned int error,
                               const char* function_name,
                               unsigned int pname,
                               float param) override;

  unsigned int PeekGLError(const char* filename,
                           int line,
                           const char* function_name) override;

  void CopyRealGLErrorsToWrapper(const char* filename,
                                 int line,
                                 const char* function_name) override;

  void ClearRealGLErrors(const char* filename,
                         int line,
                         const char* function_name) override;

 private:
  GLenum GetErrorHandleContextLoss();

  // The last error message set.
  std::string last_error_;
  // Current GL error bits.
  uint32_t error_bits_;

  ErrorStateClient* client_;
  Logger* logger_;

  DISALLOW_COPY_AND_ASSIGN(ErrorStateImpl);
};

ErrorState::ErrorState() = default;

ErrorState::~ErrorState() = default;

ErrorState* ErrorState::Create(ErrorStateClient* client, Logger* logger) {
  return new ErrorStateImpl(client, logger);
}

ErrorStateImpl::ErrorStateImpl(ErrorStateClient* client, Logger* logger)
    : error_bits_(0), client_(client), logger_(logger) {}

ErrorStateImpl::~ErrorStateImpl() = default;

uint32_t ErrorStateImpl::GetGLError() {
  // Check the GL error first, then our wrapped error.
  GLenum error = GetErrorHandleContextLoss();
  if (error == GL_NO_ERROR && error_bits_ != 0) {
    for (uint32_t mask = 1; mask != 0; mask = mask << 1) {
      if ((error_bits_ & mask) != 0) {
        error = GLES2Util::GLErrorBitToGLError(mask);
        break;
      }
    }
  }

  if (error != GL_NO_ERROR) {
    // There was an error, clear the corresponding wrapped error.
    error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
  }
  return error;
}

GLenum ErrorStateImpl::GetErrorHandleContextLoss() {
  GLenum error = glGetError();
  if (error == GL_CONTEXT_LOST_KHR) {
    client_->OnContextLostError();
    // Do not expose GL_CONTEXT_LOST_KHR, as the version of the robustness
    // extension that introduces the error is not exposed by the command
    // buffer.
    error = GL_NO_ERROR;
  }
  return error;
}

unsigned int ErrorStateImpl::PeekGLError(
    const char* filename, int line, const char* function_name) {
  GLenum error = GetErrorHandleContextLoss();
  if (error != GL_NO_ERROR) {
    SetGLError(filename, line, error, function_name, "");
  }
  return error;
}

void ErrorStateImpl::SetGLError(
    const char* filename,
    int line,
    unsigned int error,
    const char* function_name,
    const char* msg) {
  if (msg) {
    last_error_ = msg;
    logger_->LogMessage(
        filename, line,
        std::string("GL ERROR :") +
        GLES2Util::GetStringEnum(error) + " : " +
        function_name + ": " + msg);
  }
  error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
  if (error == GL_OUT_OF_MEMORY)
    client_->OnOutOfMemoryError();
}

void ErrorStateImpl::SetGLErrorInvalidEnum(
    const char* filename,
    int line,
    const char* function_name,
    unsigned int value,
    const char* label) {
  SetGLError(filename, line, GL_INVALID_ENUM, function_name,
             (std::string(label) + " was " +
             GLES2Util::GetStringEnum(value)).c_str());
}

void ErrorStateImpl::SetGLErrorInvalidParami(
    const char* filename,
    int line,
    unsigned int error,
    const char* function_name,
    unsigned int pname, int param) {
  if (error == GL_INVALID_ENUM) {
    SetGLError(
        filename, line, GL_INVALID_ENUM, function_name,
        (std::string("trying to set ") +
         GLES2Util::GetStringEnum(pname) + " to " +
         GLES2Util::GetStringEnum(param)).c_str());
  } else {
    SetGLError(
        filename, line, error, function_name,
        (std::string("trying to set ") + GLES2Util::GetStringEnum(pname) +
         " to " + base::NumberToString(param))
            .c_str());
  }
}

void ErrorStateImpl::SetGLErrorInvalidParamf(
    const char* filename,
    int line,
    unsigned int error,
    const char* function_name,
    unsigned int pname, float param) {
  SetGLError(
      filename, line, error, function_name,
      (std::string("trying to set ") +
       GLES2Util::GetStringEnum(pname) + " to " +
       base::StringPrintf("%G", param)).c_str());
}

void ErrorStateImpl::CopyRealGLErrorsToWrapper(
    const char* filename, int line, const char* function_name) {
  GLenum error;
  while ((error = GetErrorHandleContextLoss()) != GL_NO_ERROR) {
    SetGLError(filename, line, error, function_name,
               "<- error from previous GL command");
  }
}

void ErrorStateImpl::ClearRealGLErrors(
    const char* filename, int line, const char* function_name) {
  // Clears and logs all current gl errors.
  GLenum error;
  while ((error = glGetError()) != GL_NO_ERROR) {
    if (error != GL_CONTEXT_LOST_KHR && error != GL_OUT_OF_MEMORY) {
      // GL_OUT_OF_MEMORY can legally happen on lost device.
      logger_->LogMessage(
          filename, line,
          std::string("GL ERROR :") +
          GLES2Util::GetStringEnum(error) + " : " +
          function_name + ": was unhandled");
      NOTREACHED() << "GL error " << error << " was unhandled.";
    }
  }
}

}  // namespace gles2
}  // namespace gpu

