// Copyright 2014 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/texture_definition.h"

#include <list>

#include "base/memory/linked_ptr.h"
#include "base/memory/scoped_ptr.h"
#include "base/synchronization/lock.h"
#include "gpu/command_buffer/service/texture_manager.h"
#include "ui/gl/gl_image.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/scoped_binders.h"

#if !defined(OS_MACOSX)
#include "ui/gl/gl_fence_egl.h"
#include "ui/gl/gl_surface_egl.h"
#endif

namespace gpu {
namespace gles2 {

namespace {

class GLImageSync : public gfx::GLImage {
 public:
  explicit GLImageSync(const scoped_refptr<NativeImageBuffer>& buffer,
                       const gfx::Size& size);

  // Implement GLImage.
  virtual void Destroy() OVERRIDE;
  virtual gfx::Size GetSize() OVERRIDE;
  virtual bool BindTexImage(unsigned target) OVERRIDE;
  virtual void ReleaseTexImage(unsigned target) OVERRIDE;
  virtual void WillUseTexImage() OVERRIDE;
  virtual void WillModifyTexImage() OVERRIDE;
  virtual void DidModifyTexImage() OVERRIDE;

  virtual void DidUseTexImage() OVERRIDE;
  virtual void SetReleaseAfterUse() OVERRIDE;

 protected:
  virtual ~GLImageSync();

 private:
  scoped_refptr<NativeImageBuffer> buffer_;
  gfx::Size size_;

  DISALLOW_COPY_AND_ASSIGN(GLImageSync);
};

GLImageSync::GLImageSync(const scoped_refptr<NativeImageBuffer>& buffer,
                         const gfx::Size& size)
    : buffer_(buffer), size_(size) {
  if (buffer)
    buffer->AddClient(this);
}

GLImageSync::~GLImageSync() {
  if (buffer_)
    buffer_->RemoveClient(this);
}

void GLImageSync::Destroy() {}

gfx::Size GLImageSync::GetSize() {
  return size_;
}

bool GLImageSync::BindTexImage(unsigned target) {
  NOTREACHED();
  return false;
}

void GLImageSync::ReleaseTexImage(unsigned target) {
  NOTREACHED();
}

void GLImageSync::WillUseTexImage() {
  if (buffer_)
    buffer_->WillRead(this);
}

void GLImageSync::DidUseTexImage() {
  if (buffer_)
    buffer_->DidRead(this);
}

void GLImageSync::WillModifyTexImage() {
  if (buffer_)
    buffer_->WillWrite(this);
}

void GLImageSync::DidModifyTexImage() {
  if (buffer_)
    buffer_->DidWrite(this);
}

void GLImageSync::SetReleaseAfterUse() {
  NOTREACHED();
}

#if !defined(OS_MACOSX)
class NativeImageBufferEGL : public NativeImageBuffer {
 public:
  static scoped_refptr<NativeImageBufferEGL> Create(GLuint texture_id);

 private:
  NativeImageBufferEGL(EGLDisplay display, EGLImageKHR image);
  virtual ~NativeImageBufferEGL();
  virtual void AddClient(gfx::GLImage* client) OVERRIDE;
  virtual void RemoveClient(gfx::GLImage* client) OVERRIDE;
  virtual bool IsClient(gfx::GLImage* client) OVERRIDE;
  virtual void BindToTexture(GLenum target) OVERRIDE;
  virtual void WillRead(gfx::GLImage* client) OVERRIDE;
  virtual void WillWrite(gfx::GLImage* client) OVERRIDE;
  virtual void DidRead(gfx::GLImage* client) OVERRIDE;
  virtual void DidWrite(gfx::GLImage* client) OVERRIDE;

  EGLDisplay egl_display_;
  EGLImageKHR egl_image_;

  base::Lock lock_;

  struct ClientInfo {
    ClientInfo(gfx::GLImage* client);
    ~ClientInfo();

    gfx::GLImage* client;
    bool needs_wait_before_read;
    linked_ptr<gfx::GLFence> read_fence;
  };
  std::list<ClientInfo> client_infos_;
  scoped_ptr<gfx::GLFence> write_fence_;
  gfx::GLImage* write_client_;

  DISALLOW_COPY_AND_ASSIGN(NativeImageBufferEGL);
};

scoped_refptr<NativeImageBufferEGL> NativeImageBufferEGL::Create(
    GLuint texture_id) {
  EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay();
  EGLContext egl_context = eglGetCurrentContext();

  DCHECK_NE(EGL_NO_CONTEXT, egl_context);
  DCHECK_NE(EGL_NO_DISPLAY, egl_display);
  DCHECK(glIsTexture(texture_id));

  DCHECK(gfx::g_driver_egl.ext.b_EGL_KHR_image_base &&
         gfx::g_driver_egl.ext.b_EGL_KHR_gl_texture_2D_image &&
         gfx::g_driver_gl.ext.b_GL_OES_EGL_image &&
         gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync);

  const EGLint egl_attrib_list[] = {
      EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
  EGLClientBuffer egl_buffer = reinterpret_cast<EGLClientBuffer>(texture_id);
  EGLenum egl_target = EGL_GL_TEXTURE_2D_KHR; // TODO

  EGLImageKHR egl_image = eglCreateImageKHR(
      egl_display, egl_context, egl_target, egl_buffer, egl_attrib_list);

  if (egl_image == EGL_NO_IMAGE_KHR)
    return NULL;

  return new NativeImageBufferEGL(egl_display, egl_image);
}

NativeImageBufferEGL::ClientInfo::ClientInfo(gfx::GLImage* client)
    : client(client), needs_wait_before_read(true) {}

NativeImageBufferEGL::ClientInfo::~ClientInfo() {}

NativeImageBufferEGL::NativeImageBufferEGL(EGLDisplay display,
                                           EGLImageKHR image)
    : NativeImageBuffer(),
      egl_display_(display),
      egl_image_(image),
      write_fence_(new gfx::GLFenceEGL(true)),
      write_client_(NULL) {
  DCHECK(egl_display_ != EGL_NO_DISPLAY);
  DCHECK(egl_image_ != EGL_NO_IMAGE_KHR);
}

NativeImageBufferEGL::~NativeImageBufferEGL() {
  DCHECK(client_infos_.empty());
  if (egl_image_ != EGL_NO_IMAGE_KHR)
    eglDestroyImageKHR(egl_display_, egl_image_);
}

void NativeImageBufferEGL::AddClient(gfx::GLImage* client) {
  base::AutoLock lock(lock_);
  client_infos_.push_back(ClientInfo(client));
}

void NativeImageBufferEGL::RemoveClient(gfx::GLImage* client) {
  base::AutoLock lock(lock_);
  if (write_client_ == client)
    write_client_ = NULL;
  for (std::list<ClientInfo>::iterator it = client_infos_.begin();
       it != client_infos_.end();
       it++) {
    if (it->client == client) {
      client_infos_.erase(it);
      return;
    }
  }
  NOTREACHED();
}

bool NativeImageBufferEGL::IsClient(gfx::GLImage* client) {
  base::AutoLock lock(lock_);
  for (std::list<ClientInfo>::iterator it = client_infos_.begin();
       it != client_infos_.end();
       it++) {
    if (it->client == client)
      return true;
  }
  return false;
}

void NativeImageBufferEGL::BindToTexture(GLenum target) {
  DCHECK(egl_image_ != EGL_NO_IMAGE_KHR);
  glEGLImageTargetTexture2DOES(target, egl_image_);
  DCHECK_EQ(static_cast<EGLint>(EGL_SUCCESS), eglGetError());
  DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
}

void NativeImageBufferEGL::WillRead(gfx::GLImage* client) {
  base::AutoLock lock(lock_);
  if (!write_fence_.get() || write_client_ == client)
    return;

  for (std::list<ClientInfo>::iterator it = client_infos_.begin();
       it != client_infos_.end();
       it++) {
    if (it->client == client) {
      if (it->needs_wait_before_read) {
        it->needs_wait_before_read = false;
        write_fence_->ServerWait();
      }
      return;
    }
  }
  NOTREACHED();
}

void NativeImageBufferEGL::WillWrite(gfx::GLImage* client) {
  base::AutoLock lock(lock_);
  if (write_client_ != client)
    write_fence_->ServerWait();

  for (std::list<ClientInfo>::iterator it = client_infos_.begin();
       it != client_infos_.end();
       it++) {
    if (it->read_fence.get() && it->client != client)
      it->read_fence->ServerWait();
  }
}

void NativeImageBufferEGL::DidRead(gfx::GLImage* client) {
  base::AutoLock lock(lock_);
  for (std::list<ClientInfo>::iterator it = client_infos_.begin();
       it != client_infos_.end();
       it++) {
    if (it->client == client) {
      it->read_fence = make_linked_ptr(new gfx::GLFenceEGL(true));
      return;
    }
  }
  NOTREACHED();
}

void NativeImageBufferEGL::DidWrite(gfx::GLImage* client) {
  base::AutoLock lock(lock_);
  // Sharing semantics require the client to flush in order to make changes
  // visible to other clients.
  write_fence_.reset(new gfx::GLFenceEGL(false));
  write_client_ = client;
  for (std::list<ClientInfo>::iterator it = client_infos_.begin();
       it != client_infos_.end();
       it++) {
    it->needs_wait_before_read = true;
  }
}

#endif

class NativeImageBufferStub : public NativeImageBuffer {
 public:
  NativeImageBufferStub() : NativeImageBuffer() {}

 private:
  virtual ~NativeImageBufferStub() {}
  virtual void AddClient(gfx::GLImage* client) OVERRIDE {}
  virtual void RemoveClient(gfx::GLImage* client) OVERRIDE {}
  virtual bool IsClient(gfx::GLImage* client) OVERRIDE { return true; }
  virtual void BindToTexture(GLenum target) OVERRIDE {}
  virtual void WillRead(gfx::GLImage* client) OVERRIDE {}
  virtual void WillWrite(gfx::GLImage* client) OVERRIDE {}
  virtual void DidRead(gfx::GLImage* client) OVERRIDE {}
  virtual void DidWrite(gfx::GLImage* client) OVERRIDE {}

  DISALLOW_COPY_AND_ASSIGN(NativeImageBufferStub);
};

}  // anonymous namespace

// static
scoped_refptr<NativeImageBuffer> NativeImageBuffer::Create(GLuint texture_id) {
  switch (gfx::GetGLImplementation()) {
#if !defined(OS_MACOSX)
    case gfx::kGLImplementationEGLGLES2:
      return NativeImageBufferEGL::Create(texture_id);
#endif
    case gfx::kGLImplementationMockGL:
      return new NativeImageBufferStub;
    default:
      NOTREACHED();
      return NULL;
  }
}

TextureDefinition::LevelInfo::LevelInfo(GLenum target,
                                        GLenum internal_format,
                                        GLsizei width,
                                        GLsizei height,
                                        GLsizei depth,
                                        GLint border,
                                        GLenum format,
                                        GLenum type,
                                        bool cleared)
    : target(target),
      internal_format(internal_format),
      width(width),
      height(height),
      depth(depth),
      border(border),
      format(format),
      type(type),
      cleared(cleared) {}

TextureDefinition::LevelInfo::~LevelInfo() {}

TextureDefinition::TextureDefinition(
    GLenum target,
    Texture* texture,
    unsigned int version,
    const scoped_refptr<NativeImageBuffer>& image_buffer)
    : version_(version),
      target_(target),
      image_buffer_(image_buffer ? image_buffer : NativeImageBuffer::Create(
                                                      texture->service_id())),
      min_filter_(texture->min_filter()),
      mag_filter_(texture->mag_filter()),
      wrap_s_(texture->wrap_s()),
      wrap_t_(texture->wrap_t()),
      usage_(texture->usage()),
      immutable_(texture->IsImmutable()) {

  // TODO
  DCHECK(!texture->level_infos_.empty());
  DCHECK(!texture->level_infos_[0].empty());
  DCHECK(!texture->NeedsMips());
  DCHECK(texture->level_infos_[0][0].width);
  DCHECK(texture->level_infos_[0][0].height);

  scoped_refptr<gfx::GLImage> gl_image(
      new GLImageSync(image_buffer_,
                      gfx::Size(texture->level_infos_[0][0].width,
                                texture->level_infos_[0][0].height)));
  texture->SetLevelImage(NULL, target, 0, gl_image);

  // TODO: all levels
  level_infos_.clear();
  const Texture::LevelInfo& level = texture->level_infos_[0][0];
  LevelInfo info(level.target,
                 level.internal_format,
                 level.width,
                 level.height,
                 level.depth,
                 level.border,
                 level.format,
                 level.type,
                 level.cleared);
  std::vector<LevelInfo> infos;
  infos.push_back(info);
  level_infos_.push_back(infos);
}

TextureDefinition::~TextureDefinition() {
}

Texture* TextureDefinition::CreateTexture() const {
  if (!image_buffer_)
    return NULL;

  GLuint texture_id;
  glGenTextures(1, &texture_id);

  Texture* texture(new Texture(texture_id));
  UpdateTexture(texture);

  return texture;
}

void TextureDefinition::UpdateTexture(Texture* texture) const {
  gfx::ScopedTextureBinder texture_binder(target_, texture->service_id());
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s_);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t_);
  if (image_buffer_)
    image_buffer_->BindToTexture(target_);
  // We have to make sure the changes are visible to other clients in this share
  // group. As far as the clients are concerned, the mailbox semantics only
  // demand a single flush from the client after changes are first made,
  // and it is not visible to them when another share group boundary is crossed.
  // We could probably track this and be a bit smarter about when to flush
  // though.
  glFlush();

  texture->level_infos_.resize(1);
  for (size_t i = 0; i < level_infos_.size(); i++) {
    const LevelInfo& base_info = level_infos_[i][0];
    const size_t levels_needed = TextureManager::ComputeMipMapCount(
        base_info.target, base_info.width, base_info.height, base_info.depth);
    DCHECK(level_infos_.size() <= levels_needed);
    texture->level_infos_[0].resize(levels_needed);
    for (size_t n = 0; n < level_infos_.size(); n++) {
      const LevelInfo& info = level_infos_[i][n];
      texture->SetLevelInfo(NULL,
                            info.target,
                            i,
                            info.internal_format,
                            info.width,
                            info.height,
                            info.depth,
                            info.border,
                            info.format,
                            info.type,
                            info.cleared);
    }
  }
  if (image_buffer_) {
    texture->SetLevelImage(
        NULL,
        target_,
        0,
        new GLImageSync(
            image_buffer_,
            gfx::Size(level_infos_[0][0].width, level_infos_[0][0].height)));
  }

  texture->target_ = target_;
  texture->SetImmutable(immutable_);
  texture->min_filter_ = min_filter_;
  texture->mag_filter_ = mag_filter_;
  texture->wrap_s_ = wrap_s_;
  texture->wrap_t_ = wrap_t_;
  texture->usage_ = usage_;
}

bool TextureDefinition::Matches(const Texture* texture) const {
  DCHECK(target_ == texture->target());
  if (texture->min_filter_ != min_filter_ ||
      texture->mag_filter_ != mag_filter_ ||
      texture->wrap_s_ != wrap_s_ ||
      texture->wrap_t_ != wrap_t_) {
    return false;
  }

  // All structural changes should have orphaned the texture.
  if (image_buffer_ && !texture->GetLevelImage(texture->target(), 0))
    return false;

  return true;
}

}  // namespace gles2
}  // namespace gpu
