/*
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "glimp/stub/egl/display_impl.h"
#include "glimp/stub/egl/pbuffer_surface_impl.h"
#include "glimp/stub/egl/window_surface_impl.h"
#include "glimp/stub/gles/context_impl.h"
#include "nb/scoped_ptr.h"
#include "starboard/log.h"
#include "starboard/once.h"
#include "starboard/types.h"

namespace glimp {
namespace egl {

DisplayImplStub::DisplayImplStub() {
  InitializeSupportedConfigs();
}

DisplayImplStub::~DisplayImplStub() {
  for (ConfigSet::iterator iter = supported_configs_.begin();
       iter != supported_configs_.end(); ++iter) {
    delete *iter;
  }
}

bool DisplayImpl::IsValidNativeDisplayType(
    EGLNativeDisplayType native_display) {
  return native_display == EGL_DEFAULT_DISPLAY;
}

nb::scoped_ptr<DisplayImpl> DisplayImpl::Create(
    EGLNativeDisplayType native_display) {
  SB_CHECK(IsValidNativeDisplayType(native_display));
  return nb::scoped_ptr<DisplayImpl>(new DisplayImplStub());
}

DisplayImpl::VersionInfo DisplayImplStub::GetVersionInfo() {
  DisplayImpl::VersionInfo version_info;
  version_info.major = 1;
  version_info.minor = 5;
  return version_info;
}

void DisplayImplStub::InitializeSupportedConfigs() {
  Config* config = new Config();
  (*config)[EGL_RED_SIZE] = 8;
  (*config)[EGL_GREEN_SIZE] = 8;
  (*config)[EGL_BLUE_SIZE] = 8;
  (*config)[EGL_ALPHA_SIZE] = 8;
  (*config)[EGL_BUFFER_SIZE] = 32;
  (*config)[EGL_LUMINANCE_SIZE] = 0;
  (*config)[EGL_STENCIL_SIZE] = 0;
  (*config)[EGL_COLOR_BUFFER_TYPE] = EGL_RGB_BUFFER;
  (*config)[EGL_CONFORMANT] = EGL_OPENGL_ES2_BIT;
  (*config)[EGL_RENDERABLE_TYPE] = EGL_OPENGL_ES2_BIT;
  (*config)[EGL_SURFACE_TYPE] = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
  (*config)[EGL_BIND_TO_TEXTURE_RGBA] = EGL_TRUE;

  supported_configs_.insert(config);
}

nb::scoped_ptr<SurfaceImpl> DisplayImplStub::CreateWindowSurface(
    const Config* config,
    EGLNativeWindowType win,
    const AttribMap& attributes) {
  SB_DCHECK(config->find(EGL_RED_SIZE)->second == 8);
  SB_DCHECK(config->find(EGL_GREEN_SIZE)->second == 8);
  SB_DCHECK(config->find(EGL_BLUE_SIZE)->second == 8);
  SB_DCHECK(config->find(EGL_ALPHA_SIZE)->second == 8);
  SB_DCHECK(config->find(EGL_BUFFER_SIZE)->second == 32);
  SB_DCHECK(config->find(EGL_LUMINANCE_SIZE)->second == 0);
  SB_DCHECK(config->find(EGL_COLOR_BUFFER_TYPE)->second == EGL_RGB_BUFFER);
  return nb::scoped_ptr<SurfaceImpl>(new WindowSurfaceImplStub());
}

nb::scoped_ptr<SurfaceImpl> DisplayImplStub::CreatePbufferSurface(
    const Config* config,
    const AttribMap& attributes) {
  SB_DCHECK(config->find(EGL_RED_SIZE)->second == 8);
  SB_DCHECK(config->find(EGL_GREEN_SIZE)->second == 8);
  SB_DCHECK(config->find(EGL_BLUE_SIZE)->second == 8);
  SB_DCHECK(config->find(EGL_ALPHA_SIZE)->second == 8);
  SB_DCHECK(config->find(EGL_BUFFER_SIZE)->second == 32);
  SB_DCHECK(config->find(EGL_LUMINANCE_SIZE)->second == 0);
  SB_DCHECK(config->find(EGL_COLOR_BUFFER_TYPE)->second == EGL_RGB_BUFFER);
  return nb::scoped_ptr<SurfaceImpl>(new PbufferSurfaceImplStub(
      attributes.find(EGL_WIDTH)->second, attributes.find(EGL_HEIGHT)->second));
}

nb::scoped_ptr<gles::ContextImpl> DisplayImplStub::CreateContext(
    const Config* config,
    int gles_version) {
  if (gles_version == 2 || gles_version == 3) {
    return nb::scoped_ptr<gles::ContextImpl>(new gles::ContextImplStub());
  } else {
    return nb::scoped_ptr<gles::ContextImpl>();
  }
}

}  // namespace egl
}  // namespace glimp
