/*
 * Copyright 2015 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.
 */

#ifndef COBALT_RENDERER_BACKEND_EGL_GRAPHICS_CONTEXT_H_
#define COBALT_RENDERER_BACKEND_EGL_GRAPHICS_CONTEXT_H_

#include <EGL/egl.h>
#include <GLES2/gl2.h>

#include "base/memory/ref_counted.h"
#include "base/optional.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/renderer/backend/egl/render_target.h"
#include "cobalt/renderer/backend/egl/resource_context.h"
#include "cobalt/renderer/backend/egl/texture.h"
#include "cobalt/renderer/backend/egl/texture_data.h"
#include "cobalt/renderer/backend/graphics_context.h"

namespace cobalt {
namespace renderer {
namespace backend {

class GraphicsSystemEGL;

// Encapsulates a context created via EGL, which implies that it makes
// accessible the OpenGL ES API.
class GraphicsContextEGL : public GraphicsContext {
 public:
  GraphicsContextEGL(GraphicsSystem* parent_system, EGLDisplay display,
                     EGLConfig config, ResourceContext* resource_context);
  ~GraphicsContextEGL() OVERRIDE;

  GraphicsSystemEGL* system_egl();

  scoped_ptr<TextureEGL> CreateTexture(scoped_ptr<TextureDataEGL> texture_data);

  scoped_ptr<TextureEGL> CreateTextureFromRawMemory(
      const scoped_refptr<ConstRawTextureMemoryEGL>& raw_texture_memory,
      intptr_t offset, const math::Size& size, GLenum format,
      int pitch_in_bytes);

  scoped_refptr<RenderTarget> CreateOffscreenRenderTarget(
      const math::Size& dimensions) OVERRIDE;

  scoped_array<uint8_t> DownloadPixelDataAsRGBA(
      const scoped_refptr<RenderTarget>& render_target) OVERRIDE;

  // Helper class to allow one to create a RAII object that will acquire the
  // current context upon construction and release it upon destruction.
  class ScopedMakeCurrent {
   public:
    explicit ScopedMakeCurrent(GraphicsContextEGL* graphics_context)
        : graphics_context_(graphics_context),
          was_current_(graphics_context_->is_current_),
          previous_current_surface_(graphics_context_->current_surface_) {
      graphics_context_->MakeCurrent();
    }
    ScopedMakeCurrent(GraphicsContextEGL* graphics_context,
                      RenderTargetEGL* surface)
        : graphics_context_(graphics_context),
          was_current_(graphics_context_->is_current_),
          previous_current_surface_(graphics_context_->current_surface_) {
      graphics_context_->MakeCurrentWithSurface(surface);
    }
    ~ScopedMakeCurrent() {
      if (was_current_) {
        graphics_context_->MakeCurrentWithSurface(previous_current_surface_);
      } else {
        graphics_context_->ReleaseCurrentContext();
      }
    }

   private:
    GraphicsContextEGL* graphics_context_;
    bool was_current_;
    RenderTargetEGL* previous_current_surface_;
  };

  // Helper methods to make this context current and associate it with
  // a surface.  In EGL, a context is either not current or it is current and
  // associated with a surface.  For all functionality (e.g. texture creation)
  // that is provided but does not require a surface binding, null_surface_ is
  // specified as a surface.
  void MakeCurrentWithSurface(RenderTargetEGL* surface);

  // Alternatively, this call can be made to make the context current along
  // with a null surface.  You would be interested in this method if you don't
  // plan to be making any draw calls, such as if you're setting up a texture.
  void MakeCurrent();
  void ReleaseCurrentContext();

  void SwapBuffers(RenderTargetEGL* surface);

  void Blit(GLuint texture, int x, int y, int width, int height);

 private:
  // Performs a test to determine if the pixel data returned by glReadPixels
  // needs to be vertically flipped or not.  This test is expensive and so
  // it should be only done once and the results cached.
  bool ComputeReadPixelsNeedVerticalFlip();

  // Sets up all structures (like Shaders and vertex buffers) required to
  // support the Frame::BlitToRenderTarget() functionality.
  void SetupBlitObjects();

  // Clear render target.  For security reasons, we clear the display buffer
  // before rendering to it for the first 3 swaps.  This way if the application
  // does not fill the frame (presumably by accident), this clear color will
  // appear and not data that was left in the buffer from a previous process
  // that could be a security risk.  This is meant to act as a layer of
  // security, other layers are 1) The graphics driver should not let our
  // process access data from other processes in the first place and 2) The
  // application should completely cover the screen when it is rendered.
  void SecurityClear();

  EGLDisplay display_;

  // The EGL/OpenGL ES context hosted by this GraphicsContextEGL object.
  EGLContext context_;
  EGLConfig config_;

  // Keep track of whether this context has been set to current or not, and
  // if so what surface was associated with it.
  bool is_current_;
  scoped_refptr<RenderTargetEGL> current_surface_;

  // A dummy surface that is made current when we wish to execute OpenGL ES
  // commands that don't actually involve a surface in any way (e.g. texture
  // creation).
  scoped_refptr<RenderTargetEGL> null_surface_;

  // Cache whether or not BGRA texture format is supported by the underlying
  // OpenGL ES implementation.
  bool bgra_format_supported_;

  // Data required to provide BlitToRenderTarget() functionality via OpenGL ES.
  GLuint blit_vertex_shader_;
  GLuint blit_fragment_shader_;
  static const int kBlitPositionAttribute = 0;
  static const int kBlitTexcoordAttribute = 1;
  GLuint blit_program_;
  GLuint blit_vertex_buffer_;

  // Lazily evaluate whether we need to do a vertical flip when calling
  // glReadPixels(), and cache the result here when that question is answered.
  base::optional<bool> read_pixels_needs_vertical_flip_;

  // When creating and destroying textures, OpenGL calls need to be made with
  // a GL context current.  By making TextureEGL a friend class of
  // GraphicsContextEGL, the tight relationship and association of a TextureEGL
  // with a GraphicsContextEGL is made more explicit, and it also allows
  // TextureEGL to access MakeCurrent()/ReleaseCurrentContext() methods
  // of GraphicsContextEGL.
  friend class TextureEGL;
};

}  // namespace backend
}  // namespace renderer
}  // namespace cobalt

#endif  // COBALT_RENDERER_BACKEND_EGL_GRAPHICS_CONTEXT_H_
