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

#include <GLES2/gl2.h>
#ifndef GL_GLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES 1
#endif
#include <GLES2/gl2ext.h>
#include <GLES2/gl2extchromium.h>

#include <string>

#include "base/atomicops.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/logging.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "gpu/command_buffer/common/gles2_cmd_utils.h"
#include "gpu/skia_bindings/gl_bindings_skia_cmd_buffer.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gl/gl_implementation.h"

using blink::WGC3Denum;
using gpu::gles2::GLES2Implementation;
using gpu::GLInProcessContext;

namespace gpu_blink {

// static
scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>
WebGraphicsContext3DInProcessCommandBufferImpl::CreateViewContext(
    const blink::WebGraphicsContext3D::Attributes& attributes,
    bool lose_context_when_out_of_memory,
    gfx::AcceleratedWidget window) {
  DCHECK_NE(gfx::GetGLImplementation(), gfx::kGLImplementationNone);
  bool is_offscreen = false;
  return make_scoped_ptr(new WebGraphicsContext3DInProcessCommandBufferImpl(
      scoped_ptr< ::gpu::GLInProcessContext>(),
      attributes,
      lose_context_when_out_of_memory,
      is_offscreen,
      window));
}

// static
scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>
WebGraphicsContext3DInProcessCommandBufferImpl::CreateOffscreenContext(
    const blink::WebGraphicsContext3D::Attributes& attributes,
    bool lose_context_when_out_of_memory) {
  bool is_offscreen = true;
  return make_scoped_ptr(new WebGraphicsContext3DInProcessCommandBufferImpl(
      scoped_ptr< ::gpu::GLInProcessContext>(),
      attributes,
      lose_context_when_out_of_memory,
      is_offscreen,
      gfx::kNullAcceleratedWidget));
}

scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>
WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext(
    scoped_ptr< ::gpu::GLInProcessContext> context,
    const blink::WebGraphicsContext3D::Attributes& attributes) {
  bool lose_context_when_out_of_memory = false;  // Not used.
  bool is_offscreen = true;                      // Not used.
  return make_scoped_ptr(new WebGraphicsContext3DInProcessCommandBufferImpl(
      context.Pass(),
      attributes,
      lose_context_when_out_of_memory,
      is_offscreen,
      gfx::kNullAcceleratedWidget /* window. Not used. */));
}

WebGraphicsContext3DInProcessCommandBufferImpl::
    WebGraphicsContext3DInProcessCommandBufferImpl(
        scoped_ptr< ::gpu::GLInProcessContext> context,
        const blink::WebGraphicsContext3D::Attributes& attributes,
        bool lose_context_when_out_of_memory,
        bool is_offscreen,
        gfx::AcceleratedWidget window)
    : share_resources_(attributes.shareResources),
      webgl_context_(attributes.webGL),
      is_offscreen_(is_offscreen),
      window_(window),
      context_(context.Pass()) {
  ConvertAttributes(attributes, &attribs_);
  attribs_.lose_context_when_out_of_memory = lose_context_when_out_of_memory;
}

WebGraphicsContext3DInProcessCommandBufferImpl::
    ~WebGraphicsContext3DInProcessCommandBufferImpl() {
}

size_t WebGraphicsContext3DInProcessCommandBufferImpl::GetMappedMemoryLimit() {
  return context_->GetMappedMemoryLimit();
}

bool WebGraphicsContext3DInProcessCommandBufferImpl::MaybeInitializeGL() {
  if (initialized_)
    return true;

  if (initialize_failed_)
    return false;

  if (!context_) {
    // TODO(kbr): More work will be needed in this implementation to
    // properly support GPU switching. Like in the out-of-process
    // command buffer implementation, all previously created contexts
    // will need to be lost either when the first context requesting the
    // discrete GPU is created, or the last one is destroyed.
    gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
    context_.reset(GLInProcessContext::Create(
        NULL, /* service */
        NULL, /* surface */
        is_offscreen_,
        window_,
        gfx::Size(1, 1),
        NULL, /* share_context */
        share_resources_,
        attribs_,
        gpu_preference,
        ::gpu::GLInProcessContextSharedMemoryLimits(),
        nullptr,
        nullptr));
  }

  if (context_) {
    base::Closure context_lost_callback = base::Bind(
        &WebGraphicsContext3DInProcessCommandBufferImpl::OnContextLost,
        base::Unretained(this));
    context_->SetContextLostCallback(context_lost_callback);
  } else {
    initialize_failed_ = true;
    return false;
  }

  real_gl_ = context_->GetImplementation();
  setGLInterface(real_gl_);

  if (real_gl_ && webgl_context_)
    real_gl_->EnableFeatureCHROMIUM("webgl_enable_glsl_webgl_validation");

  initialized_ = true;
  return true;
}

bool
WebGraphicsContext3DInProcessCommandBufferImpl::InitializeOnCurrentThread() {
  if (!MaybeInitializeGL())
    return false;
  return context_ && !isContextLost();
}

void WebGraphicsContext3DInProcessCommandBufferImpl::SetLock(base::Lock* lock) {
  context_->SetLock(lock);
}

bool WebGraphicsContext3DInProcessCommandBufferImpl::isContextLost() {
  return context_lost_reason_ != GL_NO_ERROR;
}

WGC3Denum WebGraphicsContext3DInProcessCommandBufferImpl::
    getGraphicsResetStatusARB() {
  return context_lost_reason_;
}

::gpu::ContextSupport*
WebGraphicsContext3DInProcessCommandBufferImpl::GetContextSupport() {
  return real_gl_;
}

void WebGraphicsContext3DInProcessCommandBufferImpl::OnContextLost() {
  // TODO(kbr): improve the precision here.
  context_lost_reason_ = GL_UNKNOWN_CONTEXT_RESET_ARB;
  if (context_lost_callback_) {
    context_lost_callback_->onContextLost();
  }
}

}  // namespace gpu_blink
