// 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 "ui/gl/gl_fence.h"

#include "base/compiler_specific.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_gl_api_implementation.h"
#include "ui/gl/gl_version_info.h"

namespace gfx {

namespace {

class GLFenceNVFence: public GLFence {
 public:
  GLFenceNVFence(bool flush) {
    // What if either of these GL calls fails? TestFenceNV will return true.
    // See spec:
    // http://www.opengl.org/registry/specs/NV/fence.txt
    //
    // What should happen if TestFenceNV is called for a name before SetFenceNV
    // is called?
    //     We generate an INVALID_OPERATION error, and return TRUE.
    //     This follows the semantics for texture object names before
    //     they are bound, in that they acquire their state upon binding.
    //     We will arbitrarily return TRUE for consistency.
    glGenFencesNV(1, &fence_);
    glSetFenceNV(fence_, GL_ALL_COMPLETED_NV);
    if (flush) {
      glFlush();
    } else {
      flush_event_ = GLContext::GetCurrent()->SignalFlush();
    }
  }

  virtual bool HasCompleted() OVERRIDE {
    return !!glTestFenceNV(fence_);
  }

  virtual void ClientWait() OVERRIDE {
    if (!flush_event_ || flush_event_->IsSignaled()) {
      glFinishFenceNV(fence_);
    } else {
      LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
    }
  }

  virtual void ServerWait() OVERRIDE {
    ClientWait();
  }

 private:
  virtual ~GLFenceNVFence() {
    glDeleteFencesNV(1, &fence_);
  }

  GLuint fence_;
  scoped_refptr<GLContext::FlushEvent> flush_event_;
};

class GLFenceARBSync: public GLFence {
 public:
  GLFenceARBSync(bool flush) {
    sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
    if (flush) {
      glFlush();
    } else {
      flush_event_ = GLContext::GetCurrent()->SignalFlush();
    }
  }

  virtual bool HasCompleted() OVERRIDE {
    // Handle the case where FenceSync failed.
    if (!sync_)
      return true;

    // We could potentially use glGetSynciv here, but it doesn't work
    // on OSX 10.7 (always says the fence is not signaled yet).
    // glClientWaitSync works better, so let's use that instead.
    return  glClientWaitSync(sync_, 0, 0) != GL_TIMEOUT_EXPIRED;
  }

  virtual void ClientWait() OVERRIDE {
    if (!flush_event_ || flush_event_->IsSignaled()) {
      glClientWaitSync(sync_, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
    } else {
      LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
    }
  }

  virtual void ServerWait() OVERRIDE {
    if (!flush_event_ || flush_event_->IsSignaled()) {
      glWaitSync(sync_, 0, GL_TIMEOUT_IGNORED);
    } else {
      LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
    }
  }

 private:
  virtual ~GLFenceARBSync() {
    glDeleteSync(sync_);
  }

  GLsync sync_;
  scoped_refptr<GLContext::FlushEvent> flush_event_;
};

#if !defined(OS_MACOSX)
class EGLFenceSync : public GLFence {
 public:
  EGLFenceSync(bool flush) {
    display_ = eglGetCurrentDisplay();
    sync_ = eglCreateSyncKHR(display_, EGL_SYNC_FENCE_KHR, NULL);
    if (flush) {
      glFlush();
    } else {
      flush_event_ = GLContext::GetCurrent()->SignalFlush();
    }
  }

  virtual bool HasCompleted() OVERRIDE {
    EGLint value = 0;
    eglGetSyncAttribKHR(display_, sync_, EGL_SYNC_STATUS_KHR, &value);
    DCHECK(value == EGL_SIGNALED_KHR || value == EGL_UNSIGNALED_KHR);
    return !value || value == EGL_SIGNALED_KHR;
  }

  virtual void ClientWait() OVERRIDE {
    if (!flush_event_ || flush_event_->IsSignaled()) {
      EGLint flags = 0;
      EGLTimeKHR time = EGL_FOREVER_KHR;
      eglClientWaitSyncKHR(display_, sync_, flags, time);
    } else {
      LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
    }
  }

  virtual void ServerWait() OVERRIDE {
    if (!flush_event_ || flush_event_->IsSignaled()) {
      EGLint flags = 0;
      eglWaitSyncKHR(display_, sync_, flags);
    } else {
      LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
    }
  }


 private:
  virtual ~EGLFenceSync() {
    eglDestroySyncKHR(display_, sync_);
  }

  EGLSyncKHR sync_;
  EGLDisplay display_;
  scoped_refptr<GLContext::FlushEvent> flush_event_;
};
#endif // !OS_MACOSX

// static
GLFence* CreateFence(bool flush) {
  DCHECK(GLContext::GetCurrent())
      << "Trying to create fence with no context";

  scoped_ptr<GLFence> fence;
  // Prefer ARB_sync which supports server-side wait.
  if (g_driver_gl.ext.b_GL_ARB_sync ||
      GetGLVersionInfo()->is_es3) {
    fence.reset(new GLFenceARBSync(flush));
#if !defined(OS_MACOSX)
  } else if (g_driver_egl.ext.b_EGL_KHR_fence_sync) {
    fence.reset(new EGLFenceSync(flush));
#endif
  } else if (g_driver_gl.ext.b_GL_NV_fence) {
    fence.reset(new GLFenceNVFence(flush));
  }

  DCHECK_EQ(!!fence.get(), GLFence::IsSupported());
  return fence.release();
}

}  // namespace

GLFence::GLFence() {
}

GLFence::~GLFence() {
}

bool GLFence::IsSupported() {
  DCHECK(GetGLVersionInfo());
  return g_driver_gl.ext.b_GL_ARB_sync || GetGLVersionInfo()->is_es3 ||
#if !defined(OS_MACOSX)
         g_driver_egl.ext.b_EGL_KHR_fence_sync ||
#endif
         g_driver_gl.ext.b_GL_NV_fence;
}

GLFence* GLFence::Create() {
  return CreateFence(true);
}

GLFence* GLFence::CreateWithoutFlush() {
  return CreateFence(false);
}

}  // namespace gfx
