/*
 * 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/common/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 | EGL_OPENGL_ES3_BIT;
  (*config)[EGL_RENDERABLE_TYPE] = EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_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
