// Copyright 2016 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 GL_GLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES
#endif

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

#include "base/strings/stringize_macros.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "gpu/command_buffer/tests/gl_manager.h"
#include "gpu/command_buffer/tests/gl_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace gpu {

#if defined(OS_MACOSX)
namespace {

// clang-format off
static const char* kSimpleVertexShader = STRINGIZE(
  attribute vec2 a_position;
  varying vec2 v_texCoord;
  void main() {
    gl_Position = vec4(a_position.x, a_position.y, 0.0, 1.0);
    v_texCoord = (a_position + vec2(1.0, 1.0)) * 0.5;
  }
);
// clang-format on

// Generate fragment shader source for sampling out of a texture of |size|
// bound to |target|.
std::string GetFragmentShaderSource(unsigned target, const gfx::Size& size) {
  // clang-format off
  const char kFragmentShader[] = STRINGIZE(
    uniform SamplerType u_texture;
    varying vec2 v_texCoord;
    void main() {
      gl_FragColor = TextureLookup(u_texture, v_texCoord * TextureScale);
    }
  );
  const char kShaderFloatPrecision[] = STRINGIZE(
    precision mediump float;
  );
  // clang-format on

  switch (target) {
    case GL_TEXTURE_2D:
      return base::StringPrintf(
          "%s\n"
          "#define SamplerType sampler2D\n"
          "#define TextureLookup texture2D\n"
          "#define TextureScale vec2(1.0, 1.0)\n"
          "%s",
          kShaderFloatPrecision, kFragmentShader);
    case GL_TEXTURE_RECTANGLE_ARB:
      return base::StringPrintf(
          "%s\n"
          "#extension GL_ARB_texture_rectangle : require\n"
          "#define SamplerType sampler2DRect\n"
          "#define TextureLookup texture2DRect\n"
          "#define TextureScale vec2(%f, %f)\n"
          "%s",
          kShaderFloatPrecision, static_cast<double>(size.width()),
          static_cast<double>(size.height()), kFragmentShader);
    default:
      NOTREACHED();
      return std::string();
  }
}

}  // namespace

// A collection of tests that exercise the glCopyTexImage2D workaround. The
// parameter expresses different formats of the destination texture.
class GLCopyTexImage2DWorkaroundTest : public testing::TestWithParam<GLenum> {
 public:
  GLCopyTexImage2DWorkaroundTest() {}

 protected:
  void SetUp() override {
    GpuDriverBugWorkarounds workarounds;
    workarounds.use_intermediary_for_copy_texture_image = true;
    gl_.InitializeWithWorkarounds(GLManager::Options(), workarounds);
    gl_.set_use_iosurface_memory_buffers(true);
    DCHECK(gl_.workarounds().use_intermediary_for_copy_texture_image);
  }

  void TearDown() override {
    GLTestHelper::CheckGLError("no errors", __LINE__);
    gl_.Destroy();
  }

  GLManager gl_;
};

INSTANTIATE_TEST_SUITE_P(GLCopyTexImage2DWorkaroundTestWithParam,
                         GLCopyTexImage2DWorkaroundTest,
                         ::testing::Values(GL_RGBA));

TEST_P(GLCopyTexImage2DWorkaroundTest, UseIntermediaryTexture) {
  int width = 1;
  int height = 1;
  GLuint source_texture = 0;
  GLenum source_target = GL_TEXTURE_RECTANGLE_ARB;
  glGenTextures(1, &source_texture);
  glBindTexture(source_target, source_texture);
  glTexParameteri(source_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(source_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  std::unique_ptr<gfx::GpuMemoryBuffer> buffer(gl_.CreateGpuMemoryBuffer(
      gfx::Size(width, height), gfx::BufferFormat::RGBA_8888));
  GLuint image_id =
      glCreateImageCHROMIUM(buffer->AsClientBuffer(), width, height, GL_RGBA);
  ASSERT_NE(0u, image_id);
  glBindTexImage2DCHROMIUM(source_target, image_id);

  GLuint framebuffer = 0;
  glGenFramebuffers(1, &framebuffer);
  glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
  glFramebufferTexture2D(
      GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, source_target, source_texture, 0);
  EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
            glCheckFramebufferStatus(GL_FRAMEBUFFER));


  GLenum dest_formats[] = {GL_RGBA, GL_RGB, GL_ALPHA, GL_LUMINANCE};
  const uint8_t expectations[4][4] = {
      {33, 44, 55, 66}, {33, 44, 55, 255}, {0, 0, 0, 66}, {33, 33, 33, 255}};
  for (size_t i = 0; i < sizeof(dest_formats) / sizeof(GLenum); ++i) {
    glClearColor(33.0 / 255.0, 44.0 / 255.0, 55.0 / 255.0, 66.0 / 255.0);
    glClear(GL_COLOR_BUFFER_BIT);
    EXPECT_EQ(glGetError(), GLenum(GL_NO_ERROR));

    GLuint dest_texture = 0;
    GLenum dest_target = GL_TEXTURE_2D;
    GLenum dest_format = dest_formats[i];
    glGenTextures(1, &dest_texture);
    glBindTexture(dest_target, dest_texture);
    glTexParameteri(dest_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(dest_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glCopyTexImage2D(dest_target, 0, dest_format, 0, 0, width, height, 0);
    EXPECT_EQ(glGetError(), GLenum(GL_NO_ERROR));

    // Check that bound textures haven't changed.
    GLint boundTexture = -1;
    glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &boundTexture);
    EXPECT_EQ(glGetError(), GLenum(GL_NO_ERROR));
    EXPECT_EQ(static_cast<GLint>(source_texture), boundTexture);

    boundTexture = -1;
    glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTexture);
    EXPECT_EQ(glGetError(), GLenum(GL_NO_ERROR));
    EXPECT_EQ(static_cast<GLint>(dest_texture), boundTexture);

    glClearColor(1.0 / 255.0, 2.0 / 255.0, 3.0 / 255.0, 4.0 / 255.0);
    glClear(GL_COLOR_BUFFER_BIT);
    EXPECT_EQ(glGetError(), GLenum(GL_NO_ERROR));

    glViewport(0, 0, width, height);
    std::string fragment_shader_source =
        GetFragmentShaderSource(dest_target, gfx::Size(width, height));
    GLTestHelper::DrawTextureQuad(dest_target, kSimpleVertexShader,
                                  fragment_shader_source.c_str(), "a_position",
                                  "u_texture", nullptr);

    // Verify.
    const uint8_t* expected = expectations[i];
    EXPECT_TRUE(GLTestHelper::CheckPixels(0, 0, 1, 1, 1 /* tolerance */,
                                          expected, nullptr));
  }
}

#endif  // defined(OS_MACOSX)

}  // namespace gpu
